/**
 * drwtest - 存储设备写入可靠性验证测试工具
 * Copyright (C) 2025 huwenyupeter
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#include <winioctl.h>
#include <setupapi.h>
#include <errno.h>
#include <signal.h>
#include <vector>
#include <string>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <cstring> 
#include <malloc.h>
#include <thread>
#include <atomic>

#ifndef DRIVE_REMOVABLE
#define DRIVE_REMOVABLE 2
#endif

#ifndef BusTypeScm
#define BusTypeScm 18
#endif

#ifndef BusTypeUfs
#define BusTypeUfs 19
#endif

#define COLOR_RESET   7
#define COLOR_RED     FOREGROUND_RED | FOREGROUND_INTENSITY
#define COLOR_GREEN   FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define COLOR_YELLOW  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define COLOR_CYAN    FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define COLOR_WHITE   FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY

 // 采用单线程异步写入算法, 提升程序可靠性

 // 多线程参数
std::atomic<LONGLONG> globalBlockIndex(0);
std::atomic<LONGLONG> globalBlocksCompleted(0);
std::atomic<LONGLONG> globalBlocksToProcess(0);
std::atomic<int> globalErrors(0);

// 添加全局变量或通过参数传递来记录块状态
std::vector<int> globalBlockStatus; // 0=正常, 1=校验错误, 2=读取错误

// 保存当前的全局状态
int initial_global_state[4] = { 362436069, 521288629, 88675123,  -593279510 };

LPVOID lpBuffer = nullptr, Block = nullptr;
char RootPathName[8] = { 0 };
int immediateVerify = 1;
int testRounds = 1;
int continueOnError = 1;    //默认出错时继续
int currentRound = 0;
char selectedDrive = 0;
double totalWrittenInRound = 0;     //总写入数据量
double totalVerifiedInRound = 0;    //总验证数据量
FILE* logFile = nullptr; //当前日志
FILE* TemplogFile = nullptr; //临时日志
int totalErrors = 0;
int passedRounds = 0;
volatile BOOL g_bExit = FALSE;
int bufferSize = 1 * 1024 * 1024; //写入最小块数, 默认是1M
int largeBufferSize = 16 * 1024 * 1024; //默认缓存是16M, 然后根据写入速度决定缓冲区
int targetFileSize = 2048; //单个文件总共2048个, 相当于2048G
int deleteFilesAfterTest = 0;
DWORD bytesPerSector = 512; // 默认扇区大小

// 添加全局变量用于性能统计
double total_average_written_speed = 0;   //平均写入速度总计
double peak_written_speed = 0;      //峰值写入速度
double total_average_verified_speed = 0;  //平均校验速度总计
double peak_verified_speed = 0;     //峰值校验速度
double total_test_time = 0;         //测试总时长									 
// 性能优化参数
#define PROGRESS_UPDATE_INTERVAL 1.0 // 进度条更新间隔为1.0秒
char reportfilename[MAX_PATH] = ""; //测试报告文件
volatile BOOL g_bErrorExit = FALSE; //错误退出标志

// 定义速度延迟阈值和警告计数器
double SLOW_WRITE_THRESHOLD = 10.0;   // 写入速度延迟阈值(MB/s)
double SLOW_VERIFY_THRESHOLD = 10.0;  // 校验速度延迟阈值(MB/s)
int totalBlocks = 0; //总块数

// 超时相关的常量和变量
#define IO_TIMEOUT 30000 // 30秒超时
#define RETRY_COUNT 3   // 重试次数
volatile BOOL g_bIOTimeout = FALSE;
HANDLE g_hIOWatchdogThread = NULL;
volatile ULONGLONG lastActivityTime = 0;
CRITICAL_SECTION csTimeout; // 临界区保护
HANDLE g_hWatchdogEvent = NULL; // 全局事件句柄用于看门狗线程


// 线程参数结构
struct ThreadParams {
    HANDLE hFile;
    LONGLONG startBlock;
    LONGLONG endBlock;
    DWORD threadId;
    int bufferSizeForThisFile;
    unsigned int initial_state[4]; // 添加状态字段
    LONGLONG globalBlockOffset; // 添加全局块偏移字段
};

//定义所有函数
BOOL IsDriveAvailableEx(char driveLetter, ULONGLONG dwTimeoutMs, BOOL* pbReconnected);
HANDLE ReopenFileHandle(const char* fileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition);
// 添加函数标识符声明, 防止编译出错
void drw_init_buffer_pool();
void drw_cleanup_buffer_pool();
LPVOID drw_alloc_buffer(size_t size, size_t alignment);
void drw_free_buffer(LPVOID buffer);
void FilterModelString(char* model);
void GetConfigPath();
bool ReadPerformanceConfig(const char* model, size_t& writeSize, size_t& readSize);
void WritePerformanceConfig(const char* model, size_t writeSize, size_t readSize);
void generate_test_id();
DWORD WINAPI LogWorkerThread(LPVOID lpParam);
std::string format_time(double seconds);
void write_log(const char* format, ...);
bool is_log_file_occupied(const char* filename);
std::string find_available_log_file();
std::string generate_available_log_file();
void generate_report(const char* driveLetter, int totalRounds, int currentRound, int passedRounds, int errors, double nominalCapacity, double actualCapacity, const char* result, const char* busType, const char* exportPath);
BOOL WINAPI CtrlHandler(DWORD fdwCtrlType);
void set_console_color(WORD color);
void set_cursor_position(int x, int y);
void generate_block_with_state_legacy(LPVOID buffer, size_t block_size, unsigned int state[4]);
int verify_block_with_state_legacy(int* data, size_t block_size, unsigned int state[4]);
void generate_block_with_state(LPVOID buffer, size_t block_size, unsigned int state[4]);
int verify_block_with_state(int* data, size_t block_size, unsigned int state[4]);
void show_title();
const char* get_device_type_name(UINT type);
std::string get_disk_bus_type(char driveLetter);
BOOL get_disk_model(char driveLetter, char* model, int modelSize);
void get_drive_details(char driveLetter, char* volumeName, char* fileSystem, DWORD* serialNumber);
void get_disk_product_info(char driveLetter, char* productInfo, int infoSize);
size_t GetSystemMemorySize();
int list_drives(std::vector<std::string>& drives);
void show_drive_details(char driveLetter);
char get_user_input(const char* prompt);
void show_write_progress(HANDLE hConsole, COORD startPos, char driveLetter, const char* filename, int bufferSizeMB, double currentSpeed, double avgSpeed, double remainingMB, double remainingTime, BOOL hasError);
void show_verify_progress(HANDLE hConsole, COORD startPos, double totalTestFilesSizeMB, double totalVerifiedMB, const char* filename, int bufferSizeMB, double currentSpeed, double avgSpeed, double remainingMB, double remainingTime, BOOL hasError);
char* replace_string(const char* source, const char* oldStr, const char* newStr);
void show_result_pattern(int status, UINT deviceType);
void show_test_result(int totalRounds, int passedRounds, int errors, UINT deviceType);
int check_existing_files(char driveLetter);
double get_current_time();
void delete_test_files(char driveLetter);
DWORD WINAPI IOWatchdogThread(LPVOID lpParam);
BOOL IsDriveAvailable(char driveLetter, ULONGLONG dwTimeoutMs);
void optimize_io_parameters(char driveLetter);
DWORD WINAPI WriteThread(LPVOID lpParam);
DWORD WINAPI VerifyThread(LPVOID lpParam);
int isValidLogLine(const char* line);
time_t parseTimestamp(const char* timestamp);
void delete_temp_test_files(char driveLetter);
void export_exception_test_report(const char* logFilePath);
bool isFileLocked(const char* filename);
void show_scaled_file_status_grid(int originalTotalBlocks, const std::vector<int>& originalBlockStatus);
void show_file_status_grid(int blocksPerRow, int totalBlocks, const std::vector<int>& blockStatus);
BOOL GetDiskSectorSize(char driveLetter, DWORD& sectorSize);
std::string format_speed(double speedMBs);
void format_speed_for_display(double speedMBs, char* buffer, size_t bufferSize);
void AnalyzeFileClusterUsage(char driveLetter, const char* fileName);
void show_system_optimization_tips();
std::string get_full_path(const char* filename);
void MonitorDeviceStatus();
int get_optimal_thread_count();
void advance_state(unsigned int state[4], LONGLONG steps);
BOOL get_disk_space_info(char driveLetter, ULARGE_INTEGER& freeBytes, ULARGE_INTEGER& totalBytes);

int main(int argc, char* argv[]) {
    // 设置最高优先级
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

    // 创建看门狗事件
    g_hWatchdogEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (g_hWatchdogEvent == NULL) {
        printf("创建看门狗事件失败\n");
        return 1;
    }

    // 设置Ctrl+C处理程序
    SetConsoleCtrlHandler(CtrlHandler, TRUE);

    // 检查日志文件占用情况
    const char* logFiles[] = { "loglist.log", "temploglist.log" };
    bool hasLockedFile = false;

    for (int i = 0; i < 2; i++) {
        if (isFileLocked(get_full_path(logFiles[i]).c_str())) {
            set_console_color(COLOR_RED);
            printf("错误: 文件 %s 被其他程序占用！\n", logFiles[i]);
            printf("可能的原因: \n");
            printf("1. 另一个drwtest程序正在运行\n");
            printf("2. 文本编辑器或其他程序正在打开该文件\n");
            printf("3. 杀毒软件正在扫描该文件\n\n");
            printf("解决方法: \n");
            printf("1. 关闭正在使用该文件的程序\n");
            printf("2. 如果找不到占用程序, 可以尝试重启电脑\n");
            printf("3. 临时重命名或移动该文件\n");
            set_console_color(COLOR_RESET);
            hasLockedFile = true;
        }
    }

    if (hasLockedFile) {
        printf("\n按任意键退出...");
        _fgetchar();
        return 1;
    }

    // Check for existing temploglist.log file
    struct _stat fileStat;
    if (_stat(get_full_path("temploglist.log").c_str(), &fileStat) == 0) {
        // Check file size (2MB = 2 * 1024 * 1024)
        if (fileStat.st_size > 2 * 1024 * 1024) {
            printf("文件大小超过2M, 要花一些时间, 是否要生成测试报告？(Y/N): ");
            int choice = _fgetchar();
            if (choice == 'N' || choice == 'n') {
                // Rename the file with current timestamp
                char newName[256];
                time_t now = time(nullptr);
                struct tm timeInfo;
                localtime_s(&timeInfo, &now);
                strftime(newName, sizeof(newName), "temploglist_%Y%m%d%H%M%S.log", &timeInfo);
                if (rename(get_full_path("temploglist.log").c_str(), get_full_path(newName).c_str()) < 0)
                {
                    set_console_color(COLOR_RED);
                    printf("\n重命名文件失败！可能文件已占用, 请检查！\n 如果要继续运行程序, 请重命名temploglist.log文件或者删除temploglist.log文件！\n");
                    write_log("重命名文件失败！可能文件已占用, 请检查！\n 如果要继续运行程序, 请重命名temploglist.log文件或者删除temploglist.log文件！");
                    set_console_color(COLOR_RESET);
                    _fgetchar(); // 使用Windows特定的getchar函数
                    return 0;
                }
                printf("\n已重命名文件为: %s\n", newName);
                // Continue without generating report
            }
            else {
                export_exception_test_report(get_full_path("temploglist.log").c_str());
            }
        }
        else {
            export_exception_test_report(get_full_path("temploglist.log").c_str());
        }
    }

    // 在变量声明部分添加hFile的初始化
    HANDLE hFile = INVALID_HANDLE_VALUE;  // 初始化为无效句柄
    int exportLogReport = 0; //是否要导出测试报告
    char exportPath[MAX_PATH] = { 0 };
    total_average_written_speed = 0; //写入平均速度总计
    total_average_verified_speed = 0; //校验平均速度总计									

    // 日志初始化
    char logPath[MAX_PATH];
    GetModuleFileNameA(NULL, logPath, MAX_PATH);
    char* lastBackslash = strrchr(logPath, '\\');
    if (lastBackslash) {
        *(lastBackslash + 1) = '\0';
    }
    strcat_s(logPath, "loglist.log");
    if (fopen_s(&logFile, logPath, "a") != 0) {
        logFile = nullptr;
    }

    if (logFile) {
        write_log("===== 程序启动 =====");
    }

    // 初始化临界区
    InitializeCriticalSection(&csTimeout);

    // 创建看门狗线程
    lastActivityTime = GetTickCount64();
    g_hIOWatchdogThread = CreateThread(NULL, 0, IOWatchdogThread, NULL, 0, NULL);

    show_title();

    // 获取驱动器列表
    std::vector<std::string> drives;
    int driveCount = list_drives(drives);

    char driveLetter = 0;
    int existingFiles = 0;
    double nominalCapacity = 0; // 标称容量
    double actualCapacity = 0; // 实际容量
    std::string busType = "未知"; // 总线模式

    // 命令行参数处理
    if (argc >= 2) {
        // 第一个参数为序号
        if (isdigit(argv[1][0])) {
            int index = atoi(argv[1]) - 1;
            if (index >= 0 && index < driveCount) {
                driveLetter = drives[index][0];
                busType = get_disk_bus_type(driveLetter);
            }
        }
        // 参数为驱动器盘符
        else if (strlen(argv[1]) == 2 && argv[1][1] == ':') {
            driveLetter = toupper(argv[1][0]);
            busType = get_disk_bus_type(driveLetter);
        }
        else if (strlen(argv[1]) == 1) {
            driveLetter = toupper(argv[1][0]);
            busType = get_disk_bus_type(driveLetter);
        }

        if (argc >= 3) {
            //是否启用即时验证
            char yn = toupper(argv[2][0]);
            immediateVerify = (yn == 'Y' || yn == 'N') ? (yn == 'Y') : 1;
        }

        if (argc >= 4) {
            //输入测试轮次(默认1)
            testRounds = atoi(argv[3]);
            if (testRounds < 1) testRounds = 1;
        }

        if (argc >= 5) {
            //出错时是否继续
            char yn = toupper(argv[4][0]);
            continueOnError = (yn == 'Y' || yn == 'N') ? (yn == 'Y') : 1;
        }

        // 第五个参数: 测试后删除文件
        if (argc >= 6) {
            char yn = toupper(argv[5][0]);
            deleteFilesAfterTest = (yn == 'Y' || yn == 'N') ? (yn == 'Y') : 0;
        }

        // 第六个参数: 是否要导出测试报告
        if (argc >= 7) {
            char yn = toupper(argv[6][0]);
            exportLogReport = (yn == 'Y' || yn == 'N') ? (yn == 'Y') : 1;
        }
    }

    // 未提供驱动器盘符时提示用户选择
    while (!driveLetter && !g_bExit) {
        set_console_color(COLOR_WHITE);
        printf("请选择驱动器序号: ");
        char input[10];
        fgets(input, sizeof(input), stdin);

        if (isdigit(input[0])) {
            int index = atoi(input) - 1;
            if (index >= 0 && index < driveCount) {
                driveLetter = drives[index][0];
                busType = get_disk_bus_type(driveLetter);

                if (logFile) {
                    write_log("用户选择: %c:", driveLetter);
                }
            }
            else {
                set_console_color(COLOR_RED);
                printf("无效选择\n");
                set_console_color(COLOR_RESET);
            }
        }
        else {
            set_console_color(COLOR_RED);
            printf("无效输入\n");
            set_console_color(COLOR_RESET);
        }
    }

    if (g_bExit) {
        // 清理资源
        if (lpBuffer) _aligned_free(lpBuffer);
        if (Block) _aligned_free(Block);
        if (logFile) {
            write_log("用户提前退出");
            fclose(logFile);
        }
        return 0;
    }

    lastActivityTime = GetTickCount64();  //重置计时器										   
    // 显示驱动器详细信息
    selectedDrive = driveLetter;
    show_drive_details(driveLetter);

    // 获取磁盘扇区大小（容量信息）
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    ULARGE_INTEGER totalBytes;

    // 获取磁盘容量信息
    if (!GetDiskFreeSpaceExA(rootPath, NULL, &totalBytes, NULL)) {
        set_console_color(COLOR_RED);
        printf("无法获取磁盘信息\n");
        set_console_color(COLOR_RESET);
        return 1;
    }

    // 获取磁盘扇区大小		   
    DWORD sectorsPerCluster = 0;
    DWORD numberOfFreeClusters = 0;
    DWORD totalNumberOfClusters = 0;
    if (!GetDiskFreeSpaceA(rootPath, &sectorsPerCluster, &bytesPerSector, &numberOfFreeClusters, &totalNumberOfClusters)) {
        bytesPerSector = 512;
    }

    //获取设备类型
    UINT deviceType = GetDriveTypeA(rootPath);

    nominalCapacity = actualCapacity = (double)totalBytes.QuadPart / static_cast<double>(1024 * 1024 * 1024);

    // 未提供即时验证选项时提示用户
    if (argc < 3) {
        char input = get_user_input("是否启用即时验证?[Y/N](默认 Y): ");
        immediateVerify = (input == 'Y');

        if (input != 'Y' && input != 'N' && input != 'y' && input != 'n')
        {
            immediateVerify = 1;
        }

        if (logFile) {
            write_log("即时验证: %s", immediateVerify ? "启用" : "禁用");
        }
    }

    // 未提供测试轮次时提示用户
    if (argc < 4) {
        printf("输入测试轮次(默认1): ");
        char input[10];
        fgets(input, sizeof(input), stdin);
        testRounds = atoi(input);
        if (testRounds < 1) testRounds = 1;

        if (logFile) {
            write_log("测试轮次: %d", testRounds);
        }
    }

    // 未提供错误处理选项时提示用户
    if (argc < 5 && testRounds > 1) {
        char input = get_user_input("出错时是否继续?[Y/N](默认 Y): ");
        continueOnError = (input == 'Y');

        if (input != 'Y' && input != 'N' && input != 'y' && input != 'n')
        {
            continueOnError = 1;
        }

        if (logFile) {
            write_log("出错继续: %s", continueOnError ? "是" : "否");
        }
    }

    // 未提供删除文件选项时提示用户
    if (argc < 6) {
        char input = get_user_input("测试完成后是否删除文件?[Y/N](默认 N): ");
        deleteFilesAfterTest = (input == 'Y');

        if (input != 'Y' && input != 'N' && input != 'y' && input != 'n')
        {
            deleteFilesAfterTest = 0;
        }

        if (logFile) {
            write_log("删除文件: %s", deleteFilesAfterTest ? "是" : "否");
        }
    }

    // 第六个参数: 是否要导出测试报告
        // 在测试参数设置后添加询问
    if (argc < 7) {
        char input = get_user_input("是否导出测试报告?[Y/N](默认 Y): ");
        exportLogReport = (input == 'Y');

        if (input != 'Y' && input != 'N' && input != 'y' && input != 'n')
        {
            exportLogReport = 1;
        }

        if (exportLogReport) {
            printf("请输入导出目录(留空使用默认目录): ");
            fgets(exportPath, MAX_PATH, stdin);

            // 去除换行符
            size_t len = strlen(exportPath);
            if (len > 0 && exportPath[len - 1] == '\n') {
                exportPath[len - 1] = '\0';
            }

            // 如果留空则使用程序所在目录
            if (strlen(exportPath) == 0) {
                GetModuleFileNameA(NULL, exportPath, MAX_PATH);
                char* lastBackslash = strrchr(exportPath, '\\');
                if (lastBackslash) {
                    *lastBackslash = '\0';
                }
            }
        }

        if (logFile) {
            write_log("是否导出测试报告: %s", exportLogReport ? "是" : "否");
        }

    }

    // 更新活动时间
    EnterCriticalSection(&csTimeout);
    lastActivityTime = GetTickCount64();//重置计时器
    LeaveCriticalSection(&csTimeout);
    g_bIOTimeout = FALSE;

    //是否生成临时日志文件
    char templogPath[MAX_PATH]; //临时日志
    GetModuleFileNameA(NULL, templogPath, MAX_PATH);
    lastBackslash = strrchr(templogPath, '\\');
    if (lastBackslash) {
        *(lastBackslash + 1) = '\0';
    }
    strcat_s(templogPath, "temploglist.log");
    if (exportLogReport)
    {
        remove(templogPath); //删除临时日志文件

        if (fopen_s(&TemplogFile, templogPath, "a") != 0) {
            TemplogFile = nullptr;
        }
    }

    double test_start_time = get_current_time(); //记录测试开始时间														   

    // 调整缓冲区大小为扇区对齐
    bufferSize = (bufferSize + bytesPerSector - 1) / bytesPerSector * bytesPerSector;
    largeBufferSize = (largeBufferSize + bytesPerSector - 1) / bytesPerSector * bytesPerSector;

    // 分配内存
    lpBuffer = _aligned_malloc(bufferSize, bytesPerSector);
    Block = _aligned_malloc(bufferSize, bytesPerSector);

    if (!lpBuffer || !Block) {
        set_console_color(COLOR_RED);
        printf("内存分配失败\n");
        set_console_color(COLOR_RESET);
        if (logFile) {
            write_log("内存分配失败");
            fclose(logFile);
        }
        return 1;
    }

    if (!GetDiskFreeSpaceExA(rootPath, NULL, &totalBytes, NULL)) {
        set_console_color(COLOR_RED);
        printf("无法获取驱动器信息\n");
        set_console_color(COLOR_RESET);

        if (logFile) {
            write_log("无法获取驱动器信息");
            fclose(logFile);
        }
        _aligned_free(lpBuffer);
        _aligned_free(Block);
        return 1;
    }
    nominalCapacity = (double)totalBytes.QuadPart / static_cast<double>(1024 * 1024 * 1024);
    actualCapacity = nominalCapacity;

    if (logFile) {
        write_log("测试设备: %c:", driveLetter);
        write_log("标称容量: %.2f GB", nominalCapacity);
        write_log("实际容量: %.2f GB", actualCapacity);
        write_log("总线模式: %s", get_disk_bus_type(driveLetter).c_str());
    }

    busType = get_disk_bus_type(driveLetter);
    if (busType == "NVMe")
    {
        SLOW_WRITE_THRESHOLD = 100.0; // 100MB/s
        SLOW_VERIFY_THRESHOLD = 100.0; // 100MB/s
    }
    else
    {
        SLOW_WRITE_THRESHOLD = 10.0; // 10MB/s
        SLOW_VERIFY_THRESHOLD = 10.0; // 10MB/s
    }

    set_console_color(COLOR_YELLOW);
    printf("\n *** 开始第 1 / %d 轮测试 ***\n\n", testRounds);
    set_console_color(COLOR_RESET);

    if (logFile) {
        write_log("开始测试: 1/%d", testRounds);
    }

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO csbi;

    set_console_color(COLOR_CYAN);
    printf("                                      当前状态\n");
    printf("----------------------------------------------------------------------------------------------------\n");
    set_console_color(COLOR_RESET);

    // 获取光标位置
    GetConsoleScreenBufferInfo(hConsole, &csbi);
    COORD startPos = { 0, csbi.dwCursorPosition.Y };

    // 解决goto跳过初始化的问题
    int writeError = 0;
    int fileIndex = 1;
    double totalWritten = 0;
    double startTime = 0;
    double lastUpdateTime = 0;
    double writeStartTime = 0;

    double currentSpeed = 0; //当前速度
    double avgSpeed = 0; //平均速度
    double remainingMB = 0; //计算剩余空间/剩余验证量
    double remainingTime = 0; //计算剩余时间
    double progress = 0; //计算进度
    WORD color = COLOR_GREEN; //根据结果选择颜色,默认绿色
    double blockElapsed = 0; //块位置
    totalWrittenInRound = 0; //总写入量初始化		
    BOOL isverifyphase = FALSE; //是否跳转进入验证

    for (int round = 1; round <= testRounds && !g_bExit; round++) {
        MonitorDeviceStatus(); //设备状态监控

        currentRound = round;
        totalWrittenInRound = 0;
        g_bErrorExit = FALSE; // 在每轮测试开始处添加, 默认遇到错误时不退出
        int fileCount = 0;

        if (round > 1) {
            set_console_color(COLOR_YELLOW);
            printf("\n *** 开始第 %d / %d 轮测试 ***\n\n", round, testRounds);
            set_console_color(COLOR_RESET);

            if (logFile) {
                write_log("开始测试: %d/%d", round, testRounds);
            }

            set_console_color(COLOR_CYAN);
            printf("                                      当前状态\n");
            printf("----------------------------------------------------------------------------------------------------\n");
            set_console_color(COLOR_RESET);
            GetConsoleScreenBufferInfo(hConsole, &csbi);
            startPos = csbi.dwCursorPosition; // 更新起始位置
        }

        // 使用现有文件直接进入验证阶段
        existingFiles = check_existing_files(driveLetter);
        // 替换原有的existingFiles处理逻辑
        if (existingFiles) {
            // 初始化验证阶段需要的变量
            double totalVerified = 0;
            double verifyStart = get_current_time();
            int roundErrors = 0;
            double verifyStartTime = get_current_time();
            double lastUpdateTime = get_current_time();

            // 获取文件大小和数量
            double totalTestFilesSize = 0; //测试文件大小统计
            while (!g_bExit) {
                char tempFile[MAX_PATH];
                sprintf_s(tempFile, "%c:\\DRW%05d.BIN", driveLetter, fileCount + 1);
                if (GetFileAttributesA(tempFile) != INVALID_FILE_ATTRIBUTES) {
                    fileCount++;
                    HANDLE hFile = CreateFileA(tempFile, GENERIC_READ, FILE_SHARE_READ,
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                    if (hFile != INVALID_HANDLE_VALUE) {
                        LARGE_INTEGER fileSize;
                        GetFileSizeEx(hFile, &fileSize);
                        totalTestFilesSize += (double)fileSize.QuadPart;
                        CloseHandle(hFile);
                    }
                }
                else {
                    break;
                }
            }

            if (fileCount > 0) {
                printf("发现 %d 个测试文件, 文件总大小%.2f MB（%.0f字节）, 直接进行校验...\n\n", fileCount, totalTestFilesSize / (1024.0 * 1024.0), totalTestFilesSize);
                if (logFile) {
                    write_log("发现 %d 个现有测试文件, 文件总大小%.2f MB（%.0f字节）, 直接进行校验", fileCount, totalTestFilesSize / (1024.0 * 1024.0), totalTestFilesSize);
                }

                // 直接进入校验阶段
                isverifyphase = TRUE;
            }
            else {
                printf("\n未找到测试文件, 将创建新文件...\n\n");
                existingFiles = 0;
            }
        }

        // 写入阶段
        if (!g_bExit && !isverifyphase) {
            double startTime = get_current_time();
            double lastUpdateTime = startTime;

            int fileIndex = 1;
            while (!g_bExit) {
                char fileName[MAX_PATH];
                sprintf_s(fileName, "%c:\\DRW%05d.BIN", driveLetter, fileIndex);
                char fileNamePart[20];
                sprintf_s(fileNamePart, "DRW%05d.BIN", fileIndex);

                // 获取当前可用空间
                ULARGE_INTEGER freeBytesNow;
                if (!GetDiskFreeSpaceExA(rootPath, &freeBytesNow, NULL, NULL)) {
                    set_console_color(COLOR_RED);
                    printf("获取可用空间失败\n");
                    set_console_color(COLOR_RESET);
                    break;
                }

                // 动态调整缓冲区大小
                // 1. 决定本文件使用的缓冲区大小
                int bufferSizeForThisFile = bufferSize; // 默认使用全局bufferSize（可能是16MB）
                DWORDLONG freeSpaceMB = freeBytesNow.QuadPart / (1024 * 1024);
                int currentBufferSize = bufferSize;  // 保存当前缓冲区大小

                if (freeSpaceMB < 1 && currentSpeed == 0)
                {
                    printf("可用空间不足1M, 无法完成测试!\n");
                    writeError = 1;
                    break;
                }
                else if (freeSpaceMB < 1)
                {
                    break;
                }


                // 如果剩余空间小于2048MB, 使用1MB缓冲区
                if (freeSpaceMB < targetFileSize) {
                    bufferSizeForThisFile = 1 * 1024 * 1024;
                    if (logFile && currentBufferSize != bufferSizeForThisFile) {
                        write_log("剩余空间不足%dMB, 切换为1MB缓冲区", targetFileSize);
                    }
                }
                else {
                    //根据写入速度决定缓冲区
                    if (avgSpeed >= 400.0)
                    {
                        //写入速度超过400MB/S, 缓冲区为128M
                        bufferSizeForThisFile = 128 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 200.0)
                    {
                        //写入速度超过200MB/S, 缓冲区为64M
                        bufferSizeForThisFile = 64 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 100.0)
                    {
                        //写入速度超过100MB/S, 缓冲区为32M
                        bufferSizeForThisFile = 32 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 60.0)
                    {
                        //写入速度超过60MB/S, 缓冲区为16M
                        bufferSizeForThisFile = 16 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 30.0)
                    {
                        //写入速度超过30MB/S, 缓冲区为8M
                        bufferSizeForThisFile = 8 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 15.0)
                    {
                        //写入速度超过15MB/S, 缓冲区为4M
                        bufferSizeForThisFile = 4 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 6.0)
                    {
                        //写入速度超过6MB/S, 缓冲区为2M
                        bufferSizeForThisFile = 2 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 1.0)
                    {
                        //写入速度超过1MB/S, 缓冲区为1M
                        bufferSizeForThisFile = 1 * 1024 * 1024;
                    }
                    else
                    {
                        // 否则使用16MB缓冲区
                        bufferSizeForThisFile = largeBufferSize;
                    }

                }

                // 计算最大可写入块数（使用DWORDLONG防止整数溢出）
                DWORDLONG maxBlocks = freeBytesNow.QuadPart / bufferSizeForThisFile; // 注意这里用 bufferSizeForThisFile
                if (maxBlocks <= 0) {
                    set_console_color(COLOR_YELLOW);
                    printf("可用空间不足, 无法创建文件\n");
                    set_console_color(COLOR_RESET);
                    break;
                }

                // 确保不超出INT_MAX（安全限制）
                if (maxBlocks > INT_MAX) {
                    maxBlocks = INT_MAX;
                }

                // 限制最大文件大小
                DWORDLONG maxBlocksPerFile = (DWORDLONG)targetFileSize * 1024 * 1024 / bufferSizeForThisFile;

                // 计算可写入块数
                DWORDLONG blocksToWrite = min(maxBlocks, maxBlocksPerFile);

                // 创建文件（启用异步I/O）
                HANDLE hFile = CreateFileA(
                    fileName,
                    GENERIC_WRITE,
                    0, // 不共享
                    NULL,
                    CREATE_ALWAYS,
                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING |
                    FILE_FLAG_OVERLAPPED, // 关键: 启用异步I/O
                    NULL
                );

                if (hFile == INVALID_HANDLE_VALUE) {
                    DWORD err = GetLastError();
                    if (err == ERROR_DISK_FULL) {
                        break;
                    }
                    else {
                        set_console_color(COLOR_RED);
                        printf("文件创建失败: %s (错误: %lu)\n", fileNamePart, err);
                        set_console_color(COLOR_RESET);
                        break;
                    }
                }

                // 重置全局计数器
                globalBlockIndex.store(0);
                globalBlocksCompleted.store(0);
                globalBlocksToProcess.store(blocksToWrite);
                globalErrors.store(0);

                // 创建写入线程
                int NUM_THREADS = get_optimal_thread_count();
                //printf("检测到 %d 个CPU核心, 使用 %d 个线程\n", GetActiveProcessorCount(ALL_PROCESSOR_GROUPS), NUM_THREADS);
                std::vector<HANDLE> threads;
                std::vector<ThreadParams> threadParams(NUM_THREADS);

                // 在创建线程之前, 保存当前的全局状态
                unsigned int thread_initial_state[4];
                memcpy(thread_initial_state, initial_global_state, sizeof(initial_global_state));

                double fileStartTime = get_current_time(); // 每个文件单独的开始时间
                double fileBlocksCompleted = 0; // 每个文件单独完成的块数

                // 计算每个线程处理的块范围
                LONGLONG blocksPerThread = blocksToWrite / NUM_THREADS;
                for (int i = 0; i < NUM_THREADS; i++) {
                    threadParams[i].hFile = hFile;
                    threadParams[i].startBlock = i * blocksPerThread;
                    threadParams[i].endBlock = (i == NUM_THREADS - 1) ?
                        blocksToWrite : (i + 1) * blocksPerThread;
                    threadParams[i].bufferSizeForThisFile = bufferSizeForThisFile;
                    threadParams[i].threadId = i;

                    // 计算每个块有多少个unsigned int
                    size_t uintsPerBlock = bufferSizeForThisFile / sizeof(unsigned int);

                    // 计算该线程的初始状态
                    memcpy(threadParams[i].initial_state, initial_global_state, sizeof(initial_global_state));

                    // 根据线程的起始块位置前进状态
                    advance_state(threadParams[i].initial_state, threadParams[i].startBlock * uintsPerBlock);

                    HANDLE hThread = CreateThread(NULL, 0, WriteThread, &threadParams[i], 0, NULL);
                    if (hThread) {
                        threads.push_back(hThread);
                    }
                }

                double fileWritten = 0;
                double lastBlocksCompleted = 0;
                double lastUpdateBlocks = 0;
                double lastUpdateTime = get_current_time();
                int IoTimeoutretry = 0; //超时重试, 超过3次则退出循环

                while (static_cast<DWORD>(globalBlocksCompleted) < blocksToWrite && !g_bExit) {
                    //Sleep(200); // 减少CPU占用

                    // 进度监控循环
                    if (g_bErrorExit) {
                        break; // 立即退出循环
                    }

                    // 检查是否超时
                    if (g_bIOTimeout) {
                        set_console_color(COLOR_YELLOW);
                        printf("I/O操作超时, 等待设备响应...");
                        set_console_color(COLOR_RESET);
                        g_bIOTimeout = FALSE;

                        // 更新活动时间
                        EnterCriticalSection(&csTimeout);
                        lastActivityTime = GetTickCount64();
                        LeaveCriticalSection(&csTimeout);

                        // 可以选择重试当前操作或跳过
                        IoTimeoutretry++;
                        if (IoTimeoutretry > RETRY_COUNT - 1)
                        {
                            write_log("I/O操作超时,达到最大重试次数");
                            globalErrors++;
                            break;
                        }

                        //检查磁盘剩余空间是否不足了
                        ULARGE_INTEGER freeBytesNow;
                        if (!GetDiskFreeSpaceExA(rootPath, &freeBytesNow, NULL, NULL)) {
                            set_console_color(COLOR_RED);
                            printf("获取可用空间失败\n");
                            set_console_color(COLOR_RESET);
                            break;
                        }
                        else
                        {
                            if ((freeBytesNow.QuadPart / (1024 * 1024)) < 1)
                            {
                                set_console_color(COLOR_YELLOW);
                                printf("可用空间不足(%.2f), 停止测试!\n", static_cast<double>(freeBytesNow.QuadPart / (1024 * 1024)));
                                write_log("可用空间不足(%.2f), 停止测试!", freeBytesNow.QuadPart / (1024 * 1024));
                                set_console_color(COLOR_RESET);
                                break;
                            }
                        }
                        continue;
                    }

                    // 在写入循环中更新进度, 减少重复计算
                    double now = get_current_time();
                    if (now - lastUpdateTime > PROGRESS_UPDATE_INTERVAL) {
                        // 计算完成块数
                        double completedBlocks = (double)globalBlocksCompleted.load();
                        double newBlocks = completedBlocks - lastBlocksCompleted;
                        double timeDelta = now - lastUpdateTime;

                        // 计算速度（防止除零）
                        currentSpeed = (timeDelta > 0.001) ? (newBlocks * bufferSizeForThisFile / (1024.0 * 1024.0)) / timeDelta : 0.0;

                        // 计算平均速度
                        avgSpeed = ((now - fileStartTime) > 0.001) ? (completedBlocks * bufferSizeForThisFile / (1024.0 * 1024.0)) / (now - fileStartTime) : 0.0;

                        // 获取磁盘空间信息
                        ULARGE_INTEGER freeBytes, totalBytes;
                        if (get_disk_space_info(driveLetter, freeBytes, totalBytes)) {
                            double totalSpaceMB = (double)totalBytes.QuadPart / (1024.0 * 1024.0);
                            double usedSpaceMB = totalSpaceMB - ((double)freeBytes.QuadPart / (1024.0 * 1024.0));
                            progress = usedSpaceMB / totalSpaceMB;
                            remainingMB = (double)freeBytes.QuadPart / (1024.0 * 1024.0);
                        }

                        remainingTime = (avgSpeed > 0.1) ? remainingMB / avgSpeed : -1.0;

                        // 显示进度
                        show_write_progress(
                            hConsole,
                            startPos,
                            driveLetter,
                            fileNamePart,
                            bufferSizeForThisFile / (1024 * 1024),
                            currentSpeed,
                            avgSpeed,
                            remainingMB,
                            remainingTime,
                            globalErrors > 0
                        );

                        lastUpdateTime = now;
                        lastBlocksCompleted = completedBlocks;
                    }
                }

                // 修改为: 
                DWORD waitResult = WaitForMultipleObjects(static_cast<DWORD>(threads.size()), threads.data(), TRUE, static_cast <DWORD>(100)); // 缩短超时时间
                if (waitResult == WAIT_TIMEOUT && g_bErrorExit) {
                    // 如果超时且发生了错误, 强制终止线程
                    for (auto& hThread : threads) {
                        //TerminateThread(hThread, 0);
                        g_bExit = TRUE;
                    }
                }

                // 清理线程句柄
                for (auto& hThread : threads) {
                    CloseHandle(hThread);
                }

                // 更新总写入量
                double fileMB = blocksToWrite * bufferSizeForThisFile / (1024.0 * 1024.0);
                totalWrittenInRound += fileMB;

                // 关闭文件
                CloseHandle(hFile);

                progress = 1.0;
                // 在计算速度之前添加保护
                double now = get_current_time();
                double elapsed = now - lastUpdateTime;

                // 添加最小时间阈值, 避免除零和精度问题
                if (elapsed < 0.001) // 1毫秒阈值
                    elapsed = 0.001;

                if (currentSpeed == 0) currentSpeed = bufferSizeForThisFile / (1024 * 1024) / elapsed;
                if (avgSpeed == 0) avgSpeed = bufferSizeForThisFile / (1024 * 1024) / elapsed;


                //写入完成后, 进度条改为100%
                ULARGE_INTEGER freeBytes, totalBytes;
                if (get_disk_space_info(driveLetter, freeBytes, totalBytes)) {
                    double totalSpaceMB = (double)totalBytes.QuadPart / (1024.0 * 1024.0);
                    double usedSpaceMB = totalSpaceMB - ((double)freeBytes.QuadPart / (1024.0 * 1024.0));
                    progress = usedSpaceMB / totalSpaceMB;
                    remainingMB = (double)freeBytes.QuadPart / (1024.0 * 1024.0);
                }

                remainingTime = (avgSpeed > 0.1) ? remainingMB / avgSpeed : -1.0;

                show_write_progress(
                    hConsole,
                    startPos,
                    driveLetter,
                    fileNamePart,
                    bufferSizeForThisFile / (1024 * 1024),
                    currentSpeed,
                    avgSpeed,
                    remainingMB,
                    remainingTime,
                    (blockElapsed > SLOW_WRITE_THRESHOLD)
                );

                if (peak_written_speed < currentSpeed)
                {
                    //峰值写入速度
                    peak_written_speed = currentSpeed;
                }

                // 显示文件完成信息
                set_console_color(COLOR_GREEN);
                GetConsoleScreenBufferInfo(hConsole, &csbi);
                COORD newPos;
                newPos.X = 0;
                newPos.Y = static_cast<SHORT>(csbi.dwCursorPosition.Y + 1);
                SetConsoleCursorPosition(hConsole, newPos);
                printf("成功写入: %.0f MB\n", fileMB);
                write_log("成功写入:文件: %s, %.0f MB, 剩余空间: %.0f MB, 当前速度 %.2f MB/s, 平均速度 %.2f MB/s", fileNamePart, fileWritten, remainingMB, currentSpeed, avgSpeed);
                set_console_color(COLOR_RESET);

                fileIndex++;
            }
        }

        total_average_written_speed += avgSpeed; //平均写入速度（总计）

        if (g_bExit) break;  // 增加退出检查

        // 重置全局计数器
        globalBlockIndex.store(0);
        globalBlocksCompleted.store(0);
        globalErrors.store(0);

        int bufferSizeForThisFile = bufferSize;
        // 验证阶段
        if (immediateVerify && !g_bExit) {
            double startTime = get_current_time();
            double lastUpdateTime = startTime;

            // 在验证阶段开始前添加以下代码: 
            double totalTestFilesSizeMB = 0.0; //当前文件总大小
            double totalVerifiedMB = 0.0; // 已校验的总数据量
            char fileName[MAX_PATH];

            // 计算总块数并初始化状态向量
            fileCount = 0;
            totalBlocks = 0; // 确保totalBlocks已声明
            avgSpeed = 0; //初始化平均值
            int i = 0;
            double currentFileVerifiedMB = 0;
            double totalCurrentVerifiedMB = 0;
            while (!g_bExit)
            {
                i++;
                sprintf_s(fileName, "%c:\\DRW%05d.BIN", driveLetter, i);

                if (GetFileAttributesA(fileName) != INVALID_FILE_ATTRIBUTES) {
                    fileCount++;
                    HANDLE hFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ,
                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                    if (hFile != INVALID_HANDLE_VALUE) {
                        LARGE_INTEGER fileSize;
                        GetFileSizeEx(hFile, &fileSize);
                        totalTestFilesSizeMB += (double)fileSize.QuadPart / (1024.0 * 1024.0);
                        // 计算这个文件的块数并累加
                        totalBlocks += static_cast<int>(static_cast<double>(fileSize.QuadPart + bufferSize - 1) / static_cast<double>(bufferSize));
                        CloseHandle(hFile);
                    }
                }
                else {
                    break;
                }
            }

            // 在验证阶段开始前, 计算总块数并初始化状态向量
            globalBlockStatus.assign(totalBlocks, -1); // 初始化为-1（未知状态）

            printf("正在校验");

            //更新光标位置
            COORD newPos;
            newPos.X = 0;
            newPos.Y = static_cast<SHORT>(csbi.dwCursorPosition.Y + 1);
            SetConsoleCursorPosition(hConsole, newPos);
            GetConsoleScreenBufferInfo(hConsole, &csbi);
            startPos = csbi.dwCursorPosition;

            // 添加文件级别的超时检测
            double fileStartTime = get_current_time(); // 每个文件单独的开始时间
            double fileBlocksCompleted = 0; // 每个文件单独完成的块数
            double fileLastProgressTime = fileStartTime;
            double lastProgressValue = 0.0;

            // 在进度循环中添加
            double now = get_current_time();
            if (now - fileLastProgressTime > 30.0) { // 30秒无进展视为卡死
                if (globalBlocksCompleted - lastProgressValue < 1) {
                    set_console_color(COLOR_RED);
                    printf("\n验证过程可能已卡死, 尝试跳过此文件\n");
                    set_console_color(COLOR_RESET);
                    globalErrors++;
                    break;
                }
                fileLastProgressTime = now;
                lastProgressValue = static_cast<DWORD>(globalBlocksCompleted);
            }

            // 验证每个文件
            double totalVerified = 0;

            // 当前全局块偏移（之前所有文件的总块数）
            LONGLONG globalBlockOffset = 0;

            // 在验证循环开始前添加
            globalBlockStatus.clear();
            globalBlockStatus.resize(totalBlocks, -1); // 初始化为未知状态

            for (int i = 1; i <= fileCount && !g_bExit; i++) {
                sprintf_s(fileName, "%c:\\DRW%05d.BIN", driveLetter, i);
                char fileNamePart[20];
                sprintf_s(fileNamePart, "DRW%05d.BIN", i);

                // 创建文件句柄（启用异步I/O）
                HANDLE hFile = CreateFileA(
                    fileName,
                    GENERIC_READ,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING |
                    FILE_FLAG_OVERLAPPED, // 关键: 启用异步I/O
                    NULL
                );

                if (hFile == INVALID_HANDLE_VALUE) {
                    set_console_color(COLOR_RED);
                    printf("无法打开文件: %s\n", fileNamePart);
                    set_console_color(COLOR_RESET);
                    continue;
                }

                // 在验证阶段, 使用与写入阶段相同的缓冲区大小
                bufferSizeForThisFile = bufferSize; // 而不是重新定义

                // 如果校验文件的余量不足2048MB, 使用1MB缓冲区
                if ((totalTestFilesSizeMB - totalCurrentVerifiedMB) < targetFileSize) {
                    bufferSizeForThisFile = 1 * 1024 * 1024;
                }
                else {
                    //根据校验速度决定缓冲区
                    if (avgSpeed >= 400.0)
                    {
                        //校验速度超过400MB/S, 缓冲区为128M
                        bufferSizeForThisFile = 128 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 200.0)
                    {
                        //校验速度超过200MB/S, 缓冲区为64M
                        bufferSizeForThisFile = 64 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 100.0)
                    {
                        //校验速度超过100MB/S, 缓冲区为32M
                        bufferSizeForThisFile = 32 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 60.0)
                    {
                        //校验速度超过60MB/S, 缓冲区为16M
                        bufferSizeForThisFile = 16 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 30.0)
                    {
                        //校验速度超过30MB/S, 缓冲区为8M
                        bufferSizeForThisFile = 8 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 15.0)
                    {
                        //校验速度超过15MB/S, 缓冲区为4M
                        bufferSizeForThisFile = 4 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 6.0)
                    {
                        //校验速度超过6MB/S, 缓冲区为2M
                        bufferSizeForThisFile = 2 * 1024 * 1024;
                    }
                    else if (avgSpeed >= 1.0)
                    {
                        //校验速度超过1MB/S, 缓冲区为1M
                        bufferSizeForThisFile = 1 * 1024 * 1024;
                    }
                    else
                    {
                        // 否则使用16MB缓冲区
                        bufferSizeForThisFile = largeBufferSize;
                    }

                }

                // 获取文件大小
                LARGE_INTEGER fileSize;
                GetFileSizeEx(hFile, &fileSize);
                LONGLONG blocksInFile = (fileSize.QuadPart + bufferSizeForThisFile - 1) / bufferSizeForThisFile;

                // 设置多线程参数
                globalBlockIndex.store(0);
                globalBlocksCompleted.store(0);
                globalBlocksToProcess.store(blocksInFile);
                globalErrors.store(0);

                // 创建验证线程
                int NUM_THREADS = get_optimal_thread_count();
                //printf("检测到 %d 个CPU核心, 使用 %d 个线程\n", GetActiveProcessorCount(ALL_PROCESSOR_GROUPS), NUM_THREADS);
                std::vector<HANDLE> threads;
                std::vector<ThreadParams> threadParams(NUM_THREADS);

                // 在创建线程之前, 初始化每个线程的状态
                unsigned int thread_initial_state[4];
                memcpy(thread_initial_state, initial_global_state, sizeof(initial_global_state));

                double verifyFileStartTime = get_current_time(); // 每个验证文件单独的开始时间
                double verifyBlocksCompleted = 0; // 每个验证文件单独完成的块数

                // 计算每个线程处理的块范围
                LONGLONG blocksPerThread = blocksInFile / NUM_THREADS;
                for (int i = 0; i < NUM_THREADS; i++) {
                    threadParams[i].hFile = hFile;
                    threadParams[i].startBlock = i * blocksPerThread;
                    threadParams[i].endBlock = (i == NUM_THREADS - 1) ?
                        blocksInFile : (i + 1) * blocksPerThread;
                    threadParams[i].threadId = i;
                    // 在设置验证线程参数时, 确保: 
                    threadParams[i].globalBlockOffset = globalBlockOffset; // 当前全局偏移
                    threadParams[i].bufferSizeForThisFile = bufferSizeForThisFile; // 当前文件缓冲区大小

                    size_t uintsPerBlock = bufferSizeForThisFile / sizeof(unsigned int);

                    // 计算该线程的初始状态
                    memcpy(threadParams[i].initial_state, initial_global_state, sizeof(initial_global_state));

                    // 根据线程的起始块位置前进状态
                    advance_state(threadParams[i].initial_state, threadParams[i].startBlock * uintsPerBlock);

                    HANDLE hThread = CreateThread(NULL, 0, VerifyThread, &threadParams[i], 0, NULL);
                    if (hThread) {
                        threads.push_back(hThread);
                    }
                }

                currentFileVerifiedMB = 0;
                totalCurrentVerifiedMB = 0;
                double lastBlocksCompleted = 0;
                double lastUpdateTime = get_current_time();
                int IoTimeoutretry = 0; //超时重试, 超过3次则退出循环

                // 进度监控循环 - 添加超时机制
                while (globalBlocksCompleted < blocksInFile && !g_bExit) {
                    // 进度监控循环
                    if (g_bErrorExit) {
                        break; // 立即退出循环
                    }

                    // 检查是否超时
                    if (g_bIOTimeout) {
                        set_console_color(COLOR_YELLOW);
                        printf("I/O操作超时, 等待设备响应...");
                        set_console_color(COLOR_RESET);
                        g_bIOTimeout = FALSE;

                        // 更新活动时间
                        EnterCriticalSection(&csTimeout);
                        lastActivityTime = GetTickCount64();
                        LeaveCriticalSection(&csTimeout);

                        // 可以选择重试当前操作或跳过
                        IoTimeoutretry++;
                        if (IoTimeoutretry > RETRY_COUNT - 1)
                        {
                            write_log("I/O操作超时,达到最大重试次数");
                            globalErrors++;
                            break;
                        }

                        continue;
                    }

                    // 添加超时检测 - 防止完全卡死
                    double now = get_current_time();
                    if (now - lastUpdateTime > 10.0) { // 10秒无更新强制刷新
                        lastBlocksCompleted = static_cast<DWORD>(globalBlocksCompleted);
                        lastUpdateTime = now;
                    }

                    // 正常更新间隔
                    if (now - lastUpdateTime > PROGRESS_UPDATE_INTERVAL) {
                        double completedBlocks = (double)globalBlocksCompleted.load();
                        double newBlocks = completedBlocks - lastBlocksCompleted;
                        double timeDelta = now - lastUpdateTime;

                        // 计算速度 - 防止除以零
                        currentSpeed = (timeDelta > 0.001) ?
                            (newBlocks * bufferSizeForThisFile / (1024.0 * 1024.0)) / timeDelta : 0.0;
                        avgSpeed = avgSpeed = ((now - verifyFileStartTime) > 0.001) ? (completedBlocks * bufferSizeForThisFile / (1024.0 * 1024.0)) / (now - verifyFileStartTime) : 0.0;

                        // 根据结果选择颜色
                        WORD color = globalErrors > 0 ? COLOR_RED : COLOR_GREEN;
                        if (blockElapsed > SLOW_VERIFY_THRESHOLD) {
                            color = COLOR_YELLOW;
                        }
                        else if (blockElapsed > 0.5) {
                            color = COLOR_YELLOW;
                        }

                        // 校验计算
                        currentFileVerifiedMB = completedBlocks * bufferSizeForThisFile / (1024.0 * 1024.0);
                        totalCurrentVerifiedMB = totalVerifiedMB + currentFileVerifiedMB + totalVerified;
                        remainingMB = totalTestFilesSizeMB - totalCurrentVerifiedMB;

                        // 使用文件剩余校验量和校验速度计算: 
                        remainingTime = (avgSpeed > 0.1) ? remainingMB / avgSpeed : -1.0;

                        // 显示进度 - 即使速度为零也要更新
                        show_verify_progress(
                            hConsole,
                            startPos,
                            totalTestFilesSizeMB,
                            totalCurrentVerifiedMB,
                            fileNamePart,
                            bufferSizeForThisFile / (1024 * 1024),
                            currentSpeed,
                            avgSpeed,
                            remainingMB,
                            remainingTime,
                            globalErrors > 0
                        );

                        lastBlocksCompleted = completedBlocks;
                        lastUpdateTime = now;
                    }

                    //Sleep(200); // 减少CPU占用
                }

                double now = get_current_time();
                double elapsed = now - lastUpdateTime;

                // 等待线程结束
                WaitForMultipleObjects(static_cast<DWORD>(threads.size()), threads.data(), TRUE, static_cast<DWORD>(INFINITE));

                // 清理线程句柄
                for (auto& hThread : threads) {
                    CloseHandle(hThread);
                }

                // 更新总验证量
                double fileMB = blocksInFile * bufferSizeForThisFile / (1024.0 * 1024.0);
                totalVerified += fileMB;
                totalVerifiedInRound += fileMB;

                // 更新全局块偏移
                globalBlockOffset += (blocksInFile * bufferSizeForThisFile) / (1024 * 1024);

                // 添加最小时间阈值, 避免除零和精度问题
                if (elapsed < 0.001) // 1毫秒阈值
                    elapsed = 0.001;

                if (currentSpeed == 0) currentSpeed = bufferSizeForThisFile / (1024 * 1024) / elapsed;
                if (avgSpeed == 0) avgSpeed = bufferSizeForThisFile / (1024 * 1024) / elapsed;

                remainingMB = totalTestFilesSizeMB - totalVerified;
                remainingTime = (avgSpeed > 0.1) ? remainingMB / avgSpeed : -1.0;

                // 文件验证完成, 显示100%进度
                show_verify_progress(
                    hConsole,
                    startPos,
                    totalTestFilesSizeMB,
                    totalCurrentVerifiedMB,
                    fileNamePart,
                    bufferSizeForThisFile / (1024 * 1024),
                    currentSpeed,
                    avgSpeed,
                    remainingMB,
                    remainingTime,
                    globalErrors > 0
                );

                if (peak_verified_speed < currentSpeed)
                {
                    //峰值校验速度
                    peak_verified_speed = currentSpeed;
                }

                // 在验证每个文件结束后添加
                // 获取当前光标位置并下移一行
                GetConsoleScreenBufferInfo(hConsole, &csbi);
                COORD newPos;
                newPos.X = 0;
                newPos.Y = static_cast<SHORT>(csbi.dwCursorPosition.Y + 1);
                SetConsoleCursorPosition(hConsole, newPos);

                if (globalErrors == 0) {
                    set_console_color(COLOR_GREEN);
                    printf("成功验证: %.0f MB\n", fileMB);
                    write_log("成功验证:文件: %s, %.0f MB, 剩余空间: %.0f MB, 当前速度 %.2f MB/s, 平均速度 %.2f MB/s", fileNamePart, fileMB, remainingMB, currentSpeed, avgSpeed);
                }
                else {
                    set_console_color(COLOR_RED);
                    printf("验证失败: %.0f MB (错误: %d)\n", fileMB, globalErrors.load());
                    write_log("验证失败:文件: %s, %.0f MB, 剩余空间: %.0f MB, 当前速度 %.2f MB/s, 平均速度 %.2f MB/s", fileNamePart, fileMB, remainingMB, currentSpeed, avgSpeed);
                    totalErrors += globalErrors;
                }
                set_console_color(COLOR_RESET);

                // 关闭文件
                CloseHandle(hFile);
            }

            if (globalErrors == 0) {
                passedRounds++;
            }
        }

        total_average_verified_speed += avgSpeed; //平均验证速度总计									 

        // 验证完成后显示状态网格, 总测试2轮或者存在错误时显示网格
        if (fileCount > 0 && (testRounds <= 2 || globalErrors != 0)) {
            // 计算总块数
            int totalBlocks = 0;
            for (int i = 1; i <= fileCount; i++) {
                char fileName[MAX_PATH];
                sprintf_s(fileName, "%c:\\DRW%05d.BIN", driveLetter, i);

                HANDLE hFile = CreateFileA(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile != INVALID_HANDLE_VALUE) {
                    LARGE_INTEGER fileSize;
                    GetFileSizeEx(hFile, &fileSize);
                    LONGLONG blocksInFile = (fileSize.QuadPart + bufferSizeForThisFile - 1) / bufferSizeForThisFile;
                    //totalBlocks += (fileSize.QuadPart + bufferSize - 1) / bufferSize;
                    totalBlocks += static_cast<int>(blocksInFile);
                    CloseHandle(hFile);
                }
            }

            // 在显示状态网格前添加
            if (globalBlockStatus.empty()) {
                set_console_color(COLOR_YELLOW);
                printf("无法生成状态网格: 状态数据为空\n");
                set_console_color(COLOR_RESET);
            }
            else {
                //显示网格图
                //show_scaled_file_status_grid(totalBlocks, globalBlockStatus);
                show_scaled_file_status_grid(static_cast<int>(globalBlockStatus.size()), globalBlockStatus); //修正代码, 防止因长度不一致导致程序异常
            }
        }

        // 准备下一轮测试
        if (round < testRounds && !g_bExit) {
            delete_test_files(driveLetter);
        }

        //验证完改回默认值，确保第二轮开始写入
        isverifyphase = FALSE;

        if (g_bExit) break;  // 增加退出检查
    }
    double test_end_time = get_current_time(); //记录测试结束时间
    total_test_time = test_end_time - test_start_time; //计算总时长

    // 测试后删除文件
    if (deleteFilesAfterTest && !g_bExit) {
        delete_test_files(driveLetter);
    }


    // 获取最终总线模式信息
    std::string finalBusType = get_disk_bus_type(driveLetter);
    if (logFile) {
        write_log("总线模式: %s", finalBusType.c_str());
    }

    // 生成测试结果
    char result[256];
    if (!g_bExit) {
        show_test_result(testRounds, passedRounds, totalErrors, GetDriveTypeA(rootPath));
        if (passedRounds == testRounds && totalErrors == 0) {
            strcpy_s(result, "全部通过验证无错误");
        }
        else if (totalErrors > 0) {
            sprintf_s(result, "检测到 %d MB 数据错误", totalErrors);
        }
        else {
            sprintf_s(result, "%d/%d 轮通过验证", passedRounds, testRounds);
        }
    }
    else {
        set_console_color(COLOR_YELLOW);
        printf("\n\n用户中断 %d 轮测试\n", currentRound);

        if (totalErrors > 0) {
            set_console_color(COLOR_RED);
            printf("检测到 %d MB 数据错误, 该设备不可靠!\n", totalErrors);
        }
        else if (passedRounds > 0) {
            set_console_color(COLOR_GREEN);
            printf("已完成验证未检测到错误!\n");
        }
        else {
            set_console_color(COLOR_YELLOW);
            printf("未完成任何测试轮次, 无法确定设备状态\n");
        }
        set_console_color(COLOR_RESET);

        // 生成中断报告
        if (currentRound > 0) {
            if (passedRounds == currentRound && totalErrors == 0) {
                strcpy_s(result, "测试被中断, 已完成部分无错误");
            }
            else if (totalErrors > 0) {
                sprintf_s(result, "测试被中断, 检测到 %d MB 数据错误", totalErrors);
            }
            else {
                sprintf_s(result, "测试被中断, %d/%d 轮通过验证", passedRounds, currentRound);
            }
        }
    }

    // 在测试结束后添加导出提示
    if (exportLogReport) {
        // 生成报告（包含总线模式信息）
        generate_report(&driveLetter, testRounds, currentRound, passedRounds, totalErrors,
            nominalCapacity, actualCapacity, result, finalBusType.c_str(),
            exportLogReport ? exportPath : nullptr);

        char reportPath[MAX_PATH];
        if (reportfilename != "")
        {
            sprintf_s(reportPath, "%s\\%s", exportPath, reportfilename);
        }
        else
        {
            sprintf_s(reportPath, "%s\\test_report_*.txt", exportPath);
        }

        set_console_color(COLOR_CYAN);
        printf("\n测试报告已导出到: %s\n", exportPath);
        printf("测试报告: %s\n", reportPath);
        set_console_color(COLOR_RESET);

        //删除临时日志文件
        if (TemplogFile) {
            fclose(TemplogFile);
            TemplogFile = nullptr;
            remove(templogPath); //删除临时日志文件
        }
    }

    // 释放资源
    if (lpBuffer) {
        _aligned_free(lpBuffer);
        lpBuffer = nullptr;
    }
    if (Block) {
        _aligned_free(Block);
        Block = nullptr;
    }

    // 关闭文件句柄
    if (hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(hFile);
        hFile = INVALID_HANDLE_VALUE;
    }

    // 关闭日志文件
    if (!g_bExit)
    {
        if (logFile) {
            write_log("===== 测试结束 =====");
            fclose(logFile);
            logFile = nullptr;
        }
    }
    else
    {
        if (logFile) {
            write_log("===== 测试被中断 =====");
            fclose(logFile);
            logFile = nullptr;
        }
    }

    set_console_color(COLOR_WHITE);
    printf("\n测试完成, 按任意键退出...");
    _fgetchar(); // 使用Windows特定的getchar函数

    // 在程序退出前添加
    std::vector<int>().swap(globalBlockStatus); // 释放内存

    // 设置退出标志并唤醒看门狗线程
    g_bExit = TRUE;
    if (g_hWatchdogEvent) {
        SetEvent(g_hWatchdogEvent);
    }

    // 等待看门狗线程退出
    if (g_hIOWatchdogThread) {
        WaitForSingleObject(g_hIOWatchdogThread, 1000);
        CloseHandle(g_hIOWatchdogThread);
        g_hIOWatchdogThread = NULL;
    }

    // 关闭事件句柄
    if (g_hWatchdogEvent) {
        CloseHandle(g_hWatchdogEvent);
        g_hWatchdogEvent = NULL;
    }

    // 删除临界区
    DeleteCriticalSection(&csTimeout);

    return 0;

}

//获取CPU线程并计算
int get_optimal_thread_count() {
    //SYSTEM_INFO sysInfo;
    //GetSystemInfo(&sysInfo);

    //// 核心数除以2, 至少保留1个线程
    //int threadCount = sysInfo.dwNumberOfProcessors / 2;
    return 1; //单线程
}

//状态前进函数
void advance_state(unsigned int state[4], LONGLONG steps) {
    for (LONGLONG j = 0; j < steps; j++) {
        unsigned int temp = state[0] ^ (state[0] << 11);
        state[0] = state[1];
        state[1] = state[2];
        state[2] = state[3];
        state[3] ^= temp ^ ((temp ^ (state[3] >> 11)) >> 8);
    }
}

//格式化时间
std::string format_time(double seconds) {
    int hours = static_cast<int>(seconds) / 3600;
    int minutes = (static_cast<int>(seconds) % 3600) / 60;
    int secs = static_cast<int>(seconds) % 60;
    char time_test[MAX_PATH];
    sprintf_s(time_test, sizeof(time_test), "%02d:%02d:%02d", hours, minutes, secs);

    return std::string(time_test);
}
void write_log(const char* format, ...) {
    if (!logFile) return;

    time_t now = time(NULL);
    struct tm tm_info;
    localtime_s(&tm_info, &now);
    char time_str[20];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_info);

    va_list args;
    va_start(args, format);

    fprintf(logFile, "[%s] ", time_str);
    vfprintf(logFile, format, args);
    fprintf(logFile, "\n");
    fflush(logFile);

    if (TemplogFile) {
        fprintf(TemplogFile, "[%s] ", time_str);
        vfprintf(TemplogFile, format, args);
        fprintf(TemplogFile, "\n");
        fflush(TemplogFile);
    }

    va_end(args);
}

//测试报告
void generate_report(const char* driveLetter, int totalRounds, int currentRound, int passedRounds, int errors,
    double nominalCapacity, double actualCapacity, const char* result, const char* busType, const char* exportPath = nullptr) {
    char reportPath[MAX_PATH];

    if (exportPath && strlen(exportPath) > 0) {
        strcpy_s(reportPath, exportPath);
        // 确保路径以反斜杠结尾
        size_t len = strlen(reportPath);
        if (reportPath[len - 1] != '\\') {
            strcat_s(reportPath, "\\");
        }
    }
    else {
        GetModuleFileNameA(NULL, reportPath, MAX_PATH);
        // ... 原有路径处理 ...
        char* lastBackslash = strrchr(reportPath, '\\');
        if (lastBackslash) {
            *(lastBackslash + 1) = '\0';
        }
    }
    time_t now = time(NULL);
    struct tm tm_info;
    localtime_s(&tm_info, &now);
    char file_time_str[20];
    strftime(file_time_str, sizeof(file_time_str), "%Y%m%d%H%M%S", &tm_info);
    // 文件名生成方式
    char filename[MAX_PATH];
    sprintf_s(filename, sizeof(filename), "test_report_%s.txt", file_time_str);
    strcat_s(reportPath, MAX_PATH, filename);

    // 保存文件名到全局变量
    if (exportPath) strcpy_s(reportfilename, sizeof(reportfilename), filename);

    FILE* report;
    if (fopen_s(&report, reportPath, "w") != 0 || !report) return;

    char time_str[20];
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_info);

    fprintf(report, "USB/SSD写入可靠性验证测试\n");
    fprintf(report, "测试时间: %s\n", time_str);
    fprintf(report, "==================================================\n\n");

    fprintf(report, "版本: v1.5 Release 1.4\n");
    if (driveLetter != nullptr && *driveLetter != '\0') {
        fprintf(report, "测试设备: %c:\n", *driveLetter);
    }
    else {
        fprintf(report, "测试设备: 未知设备\n");
    }
    fprintf(report, "连接模式: %s\n", busType);
    fprintf(report, "总执行轮次: %d\n", totalRounds);
    fprintf(report, "已执行轮次: %d\n", currentRound);
    fprintf(report, "通过轮次: %d\n", passedRounds);
    fprintf(report, "错误数据量: %d MB\n", errors);
    fprintf(report, "标称容量: %.2f GB\n", nominalCapacity);
    fprintf(report, "实际容量: %.2f GB\n", actualCapacity);
    fprintf(report, "测试结果: %s\n\n", result);

    // 添加性能统计
    if (currentRound < 1)  currentRound = 1; //防止除0导致触发BUG
    fprintf(report, "性能统计:\n");
    fprintf(report, "--------------------------------------------------\n");
    int temptotalRounds = currentRound; //检查写入和校验大小是否一至, 如果不一致则减1
    if ((totalVerifiedInRound / totalWrittenInRound) <= currentRound)
    {
        temptotalRounds = temptotalRounds - 1;
        if (temptotalRounds < 1) temptotalRounds = 1;//防止除0导致触发BUG
    }
    fprintf(report, "平均写入速度: %.2f MB/s\n", total_average_written_speed / temptotalRounds);
    fprintf(report, "峰值写入速度: %.2f MB/s\n", peak_written_speed);
    fprintf(report, "总写入数据量: %.2f MB\n", totalWrittenInRound);
    fprintf(report, "平均验证速度: %.2f MB/s\n", total_average_verified_speed / currentRound);
    fprintf(report, "峰值验证速度: %.2f MB/s\n", peak_verified_speed);
    fprintf(report, "总验证数据量: %.2f MB\n", totalVerifiedInRound);
    fprintf(report, "测试总时长: %s\n", format_time(total_test_time).c_str());

    //确保日志文件已经完全写入
    if (TemplogFile) {
        fflush(TemplogFile);  // 强制刷新缓冲区
        fclose(TemplogFile);
        // 添加延迟确保文件系统完成写入
        Sleep(1000);  // 等待1000毫秒
    }

    // 添加重试机制打开日志文件
    FILE* ttemplogFile = nullptr;
    int retryCount = 0;
    const int maxRetries = 10; //重试次数

    char templogPath[MAX_PATH]; //临时日志
    GetModuleFileNameA(NULL, templogPath, MAX_PATH);
    char* lastBackslash = strrchr(templogPath, '\\');
    if (lastBackslash) {
        *(lastBackslash + 1) = '\0';
    }
    strcat_s(templogPath, "temploglist.log");
    while (retryCount < maxRetries) {
        if (fopen_s(&ttemplogFile, templogPath, "r") == 0 && ttemplogFile) {
            break;  // 成功打开
        }
        printf("打开日志失败, 可能系统在繁忙, 请稍候！\n");
        retryCount++;
        Sleep(1000);  // 等待1000毫秒后重试
    }

    if (ttemplogFile) {
        fprintf(report, "详细日志记录:\n");
        fprintf(report, "--------------------------------------------------\n");

        char line[256];
        while (fgets(line, sizeof(line), ttemplogFile)) {
            fprintf(report, "%s", line);
        }
        fclose(ttemplogFile);
    }
    else {
        fprintf(report, "无法读取日志文件\n");
    }

    fclose(report);
}

BOOL WINAPI CtrlHandler(DWORD fdwCtrlType) {
    switch (fdwCtrlType) {
    case CTRL_C_EVENT: // 添加按CTRL+C的处理
        g_bExit = TRUE;
        if (g_hWatchdogEvent) {
            SetEvent(g_hWatchdogEvent);
        }
        return TRUE;
    case CTRL_CLOSE_EVENT: // 添加对关闭事件的处理
        g_bExit = TRUE;
        if (g_hWatchdogEvent) {
            SetEvent(g_hWatchdogEvent);
        }
        return TRUE;
    default:
        return FALSE;
    }
}

void set_console_color(WORD color) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, color);
}

void set_cursor_position(int x, int y) {
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD pos = { (SHORT)x, (SHORT)y };
    SetConsoleCursorPosition(hConsole, pos);
}

void generate_block_with_state(LPVOID buffer, size_t block_size, unsigned int state[4]) {
    unsigned int* ptr = (unsigned int*)buffer;
    size_t blockCount = block_size / sizeof(unsigned int);

    // 使用传入的状态而不是全局状态
    unsigned int s0 = state[0];
    unsigned int s1 = state[1];
    unsigned int s2 = state[2];
    unsigned int s3 = state[3];

    for (size_t i = 0; i < blockCount; i++) {
        unsigned int temp = s0 ^ (s0 << 11);
        s0 = s1;
        s1 = s2;
        s2 = s3;
        s3 ^= temp ^ ((temp ^ (s3 >> 11)) >> 8);
        *ptr++ = s3;
    }

    // 更新状态以备下一个块使用
    state[0] = s0;
    state[1] = s1;
    state[2] = s2;
    state[3] = s3;
}

// 修改验证函数
int verify_block_with_state(int* data, size_t block_size, unsigned int state[4]) {
    // 使用传入的状态而不是全局状态
    unsigned int s0 = state[0];
    unsigned int s1 = state[1];
    unsigned int s2 = state[2];
    unsigned int s3 = state[3];

    size_t blockCount = block_size / sizeof(unsigned int);
    for (size_t i = 0; i < blockCount; i++) {
        unsigned int temp = s0 ^ (s0 << 11);
        s0 = s1;
        s1 = s2;
        s2 = s3;
        s3 ^= temp ^ ((temp ^ (s3 >> 11)) >> 8);

        if (*data++ != s3) {
            return 0;
        }
    }

    // 更新状态
    state[0] = s0;
    state[1] = s1;
    state[2] = s2;
    state[3] = s3;

    return 1;
}

// 标题显示
void show_title() {
    set_console_color(COLOR_CYAN);
    printf("\n");
    printf("\n");
    printf("\t┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");
    printf("\t┃\t 存储设备写入可靠性验证测试 v1.5 Release 1.4 \t ┃\n");
    printf("\t┃\t   2025-10-18   by    huwenyupeter      \t ┃\n");
    printf("\t┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n");
    printf("\n");
    set_console_color(COLOR_RESET);
}

// 设备类型名称
const char* get_device_type_name(UINT type) {
    switch (type) {
    case DRIVE_FIXED:      return "固定磁盘";
    case DRIVE_REMOVABLE:  return "可移动设备";
    case DRIVE_CDROM:      return "光驱";
    case DRIVE_RAMDISK:    return "RAM磁盘";
    case DRIVE_UNKNOWN:    return "未知设备";
    default:               return "未知设备";
    }
}

// 磁盘总线类型
std::string get_disk_bus_type(char driveLetter) {
    std::string busType = "未知";
    char path[7] = { '\\', '\\', '.', '\\', driveLetter, ':', '\0' };

    HANDLE hDevice = CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
        return busType;
    }

    STORAGE_PROPERTY_QUERY query{};
    query.PropertyId = StorageAdapterProperty;
    query.QueryType = PropertyStandardQuery;

    DWORD bytesReturned = 0;
    BYTE buffer[1024] = { 0 };

    if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(query), buffer, sizeof(buffer), &bytesReturned, NULL)) {

        STORAGE_ADAPTER_DESCRIPTOR* adapter = (STORAGE_ADAPTER_DESCRIPTOR*)buffer;
        switch (adapter->BusType) {
        case BusTypeScsi:       busType = "SCSI"; break;
        case BusTypeAtapi:      busType = "ATAPI"; break;
        case BusTypeAta:        busType = "ATA"; break;
        case BusType1394:       busType = "IEEE 1394"; break;
        case BusTypeSsa:        busType = "SSA"; break;
        case BusTypeFibre:      busType = "光纤通道"; break;
        case BusTypeUsb:        busType = "USB"; break;
        case BusTypeRAID:       busType = "RAID"; break;
        case BusTypeiScsi:      busType = "iSCSI"; break;
        case BusTypeSas:        busType = "SAS"; break;
        case BusTypeSata:       busType = "SATA"; break;
        case BusTypeSd:         busType = "SD"; break;
        case BusTypeMmc:        busType = "MMC"; break;
        case BusTypeVirtual:    busType = "虚拟磁盘"; break;
        case BusTypeFileBackedVirtual: busType = "文件虚拟化"; break;
        case BusTypeSpaces:     busType = "存储空间"; break;
        case BusTypeNvme:       busType = "NVMe"; break;
        case BusTypeScm:        busType = "SCM"; break;
        case BusTypeUfs:        busType = "UFS"; break;
        case BusTypeMax:        busType = "Max"; break;
        default:                busType = "未知";
        }
    }

    CloseHandle(hDevice);
    return busType;
}

// 磁盘型号
BOOL get_disk_model(char driveLetter, char* model, int modelSize) {
    char path[7] = { '\\', '\\', '.', '\\', driveLetter, ':', '\0' };
    HANDLE hDevice = CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hDevice != INVALID_HANDLE_VALUE) {
        // 修改为使用宽字符版本获取产品信息
        STORAGE_PROPERTY_QUERY storagePropertyQuery;
        storagePropertyQuery.PropertyId = StorageDeviceProperty;
        storagePropertyQuery.QueryType = PropertyStandardQuery;

        DWORD bytesReturned = 0;
        BYTE buffer[1024] = { 0 };  // 增加缓冲区大小

        if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
            &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
            buffer, sizeof(buffer), &bytesReturned, NULL)) {

            STORAGE_DEVICE_DESCRIPTOR* deviceDesc = (STORAGE_DEVICE_DESCRIPTOR*)buffer;

            // 使用宽字符转换解决乱码问题
            if (deviceDesc->ProductIdOffset > 0) {
                const char* productId = (const char*)deviceDesc + deviceDesc->ProductIdOffset;

                // 转换为宽字符再转回多字节
                int wlen = MultiByteToWideChar(CP_ACP, 0, productId, -1, NULL, 0);
                wchar_t* wbuffer = new wchar_t[wlen];
                MultiByteToWideChar(CP_ACP, 0, productId, -1, wbuffer, wlen);

                WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, model, modelSize, NULL, NULL);
                delete[] wbuffer;

                CloseHandle(hDevice);
                return TRUE;
            }
        }
        CloseHandle(hDevice);
    }

    // 备用方法: 使用卷标作为型号
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    char volumeName[256] = { 0 };
    char fileSystem[10] = { 0 };
    DWORD serialNumber = 0, maxComponentLen = 0, fileSystemFlags = 0;

    if (GetVolumeInformationA(rootPath, volumeName, sizeof(volumeName),
        &serialNumber, &maxComponentLen, &fileSystemFlags,
        fileSystem, sizeof(fileSystem))) {

        if (strlen(volumeName) > 0) {
            strncpy_s(model, modelSize, volumeName, modelSize - 1);
            model[modelSize - 1] = '\0';
            return TRUE;
        }
    }

    // 默认值
    UINT type = GetDriveTypeA(rootPath);
    if (type == DRIVE_FIXED) strcpy_s(model, modelSize, "固定磁盘");
    else if (type == DRIVE_REMOVABLE) strcpy_s(model, modelSize, "可移动设备");
    else if (type == DRIVE_CDROM) strcpy_s(model, modelSize, "光驱");
    else strcpy_s(model, modelSize, "存储设备");

    return TRUE;
}

// 驱动器详情
void get_drive_details(char driveLetter, char* volumeName, char* fileSystem, DWORD* serialNumber) {
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    DWORD maxComponentLen = 0, fileSystemFlags = 0;

    GetVolumeInformationA(rootPath, volumeName, 256,
        serialNumber, &maxComponentLen, &fileSystemFlags,
        fileSystem, 100);
}

// 产品信息
void get_disk_product_info(char driveLetter, char* productInfo, int infoSize) {
    // 确保缓冲区初始化
    memset(productInfo, 0, infoSize);

    char path[7] = { '\\', '\\', '.', '\\', driveLetter, ':', '\0' };
    HANDLE hDevice = CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hDevice != INVALID_HANDLE_VALUE) {
        STORAGE_PROPERTY_QUERY query;
        memset(&query, 0, sizeof(query));
        query.PropertyId = StorageDeviceProperty;
        query.QueryType = PropertyStandardQuery;

        DWORD bytesReturned;
        BYTE buffer[1024] = { 0 };

        if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
            &query, sizeof(query), buffer, sizeof(buffer), &bytesReturned, NULL)) {

            STORAGE_DEVICE_DESCRIPTOR* deviceDesc = (STORAGE_DEVICE_DESCRIPTOR*)buffer;

            // 获取产品ID字符串
            const char* productId1 = nullptr;
            if (deviceDesc->VendorIdOffset > 0 && deviceDesc->VendorIdOffset < sizeof(buffer)) {
                productId1 = (const char*)buffer + deviceDesc->VendorIdOffset;
            }

            const char* productId2 = nullptr;

            if (deviceDesc->ProductIdOffset > 0 && deviceDesc->ProductIdOffset < sizeof(buffer)) {
                productId2 = (const char*)buffer + deviceDesc->ProductIdOffset;
            }

            // 安全拼接字符串
            char temp[512] = { 0 };

            // 检查productId1是否有效
            if (productId1 != nullptr && *productId1 != '\0') {
                strncat_s(temp, sizeof(temp), productId1, _TRUNCATE);
            }

            // 检查productId2是否有效
            if (productId2 != nullptr && *productId2 != '\0') {
                // 如果第一个字符串非空, 添加空格分隔
                if (strlen(temp) > 0) {
                    strncat_s(temp, sizeof(temp), " ", _TRUNCATE);
                }
                strncat_s(temp, sizeof(temp), productId2, _TRUNCATE);
            }

            // 如果两个字符串都为空, 设置默认值
            if (strlen(temp) == 0) {
                strncpy_s(temp, sizeof(temp), "未知设备", _TRUNCATE);
            }

            // 清理字符串
            int len = (int)strlen(temp);
            for (int i = 0; i < len; i++) {
                if (temp[i] < 32 || temp[i] > 126) {
                    temp[i] = ' ';
                }
            }

            // 修剪空格
            char* start = temp;
            char* end = temp + len - 1;
            while (*start && isspace((unsigned char)*start)) start++;
            while (end > start && isspace((unsigned char)*end)) end--;
            *(end + 1) = '\0';

            if (start != temp) {
                memmove(temp, start, end - start + 2);
            }

            // 复制到最终输出
            strncpy_s(productInfo, infoSize, temp, _TRUNCATE);

            CloseHandle(hDevice);
            return;
        }
        CloseHandle(hDevice);
    }

    // 备用方法: 使用卷标或设备类型
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    char volumeName[256] = { 0 };
    char fileSystem[10] = { 0 };
    DWORD serialNumber = 0, maxComponentLen = 0, fileSystemFlags = 0;

    if (GetVolumeInformationA(rootPath, volumeName, sizeof(volumeName), &serialNumber,
        &maxComponentLen, &fileSystemFlags, fileSystem, sizeof(fileSystem)) &&
        volumeName[0] != '\0') {
        strncpy_s(productInfo, infoSize, volumeName, _TRUNCATE);
    }
    else {
        UINT type = GetDriveTypeA(rootPath);
        if (type == DRIVE_FIXED)
            strcpy_s(productInfo, infoSize, "固定硬盘");
        else if (type == DRIVE_REMOVABLE)
            strcpy_s(productInfo, infoSize, "可移动设备");
        else if (type == DRIVE_CDROM)
            strcpy_s(productInfo, infoSize, "光驱");
        else
            strcpy_s(productInfo, infoSize, "存储设备");
    }
}

// 驱动器列表
int list_drives(std::vector<std::string>& drives) {
    set_console_color(COLOR_YELLOW);
    char path[MAX_PATH];
    GetModuleFileNameA(NULL, path, MAX_PATH);

    printf("正确使用格式:\n");
    printf("%s [驱动器号] [V] [S] [C] [D] [P]\n\n", path);
    printf(" \"驱动器号\" 表示目标驱动器字母\n");
    printf("     \"[V]\" 表示是否实时验证(默认为Y)[Y/N]\n");
    printf("     \"[S]\" 表示执行轮次数量（数字）\n");
    printf("     \"[C]\" 表示出错时继续(默认为Y)[Y/N]\n");
    printf("     \"[D]\" 表示是否删除文件(默认为N)[Y/N]\n");
    printf("     \"[P]\" 表示是否导出测试报告(默认为Y)[Y/N]\n\n");
    printf("***********************************\n\n");

    printf("说明:\n");
    printf("* 设备类型: 固定磁盘/可移动设备\n");
    printf("* 连接模式: 显示设备的连接模式(SATA, NVMe等)\n");
    printf("* 产品型号: 显示设备的产品型号(如西数、希捷等)\n");
    printf("* 程序说明: 该程序采用单线程技术, 解决兼容性问题, 提高硬盘写入和校验速度, 看门狗自检程序, 防止安全软件导致程序意外暂停, 增强程序稳定性、可靠性;总测试2轮或者存在错误时显示网格;\n");
    printf("* 网格说明: 总测试2轮以内或者存在数据错误时, 测试结束显示网格;\n");
    printf("* 兼容说明: 可兼容drwtest V1.5以下版本的数据\n\n");
    set_console_color(COLOR_RESET);
    set_console_color(COLOR_RED);
    printf("注意事项与免责声明:\n");
    printf("1.数据破坏性:此程序会擦除目标磁盘上的部分数据！请在运行前备份目标设备上的所有重要数据。\n");
    printf("2.设备风险:长时间、高强度的读写测试可能会对质量较差的存储设备造成不可逆的损害, 加速其老化或直接导致损坏。请知悉此风险。\n");
    printf("3.正确选择设备:运行时请极度小心, 确保选择的是正确的、需要测试的可移动设备, 切勿误选系统硬盘。\n");
    printf("4.免责声明:本工具按“原样”提供, 作者和开发者不对因使用此软件而导致的任何数据丢失、设备损坏或任何其他直接或间接损失承担任何责任。使用者需自行承担所有风险。\n\n");
    set_console_color(COLOR_RESET);

    set_console_color(COLOR_CYAN);
    printf("序号     设备类型   驱动器   连接模式              产品型号                         文件系统   序列号         总容量\n");
    printf("------------------------------------------------------------------------------------------------------------------------\n");
    set_console_color(COLOR_RESET);

    char drivesList[128];
    DWORD len = GetLogicalDriveStringsA(sizeof(drivesList), drivesList);
    int driveCount = 0;

    if (len == 0 || len > sizeof(drivesList)) return 0;

    char* drive = drivesList;
    while (*drive) {
        UINT type = GetDriveTypeA(drive);
        const char* typeName = get_device_type_name(type);
        std::string busType = get_disk_bus_type(drive[0]);

        ULARGE_INTEGER freeBytes, totalBytes, totalFreeBytes;
        if (GetDiskFreeSpaceExA(drive, &freeBytes, &totalBytes, &totalFreeBytes)) {
            double totalGB = (double)totalBytes.QuadPart / static_cast<double>(1024 * 1024 * 1024);
            char volumeName[256] = { 0 };
            char fileSystem[10] = { 0 };
            DWORD serialNumber = 0;
            char productInfo[256] = { 0 };

            get_drive_details(drive[0], volumeName, fileSystem, &serialNumber);
            get_disk_product_info(drive[0], productInfo, sizeof(productInfo));

            drives.push_back(std::string(1, drive[0]));

            printf(" %-2d      %-10s    %-4c   %-10s      %-35s  %-10s  %08lX    %8.2f GB\n",
                driveCount + 1, typeName, drive[0], busType.c_str(), productInfo, fileSystem,
                (unsigned long)serialNumber, totalGB);

            driveCount++;
        }

        drive += strlen(drive) + 1;
    }
    printf("\n");
    return driveCount;
}

// 驱动器详情显示
void show_drive_details(char driveLetter) {
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    std::string busType = get_disk_bus_type(driveLetter);
    char productInfo[256] = { 0 };
    get_disk_product_info(driveLetter, productInfo, sizeof(productInfo));

    ULARGE_INTEGER freeBytes, totalBytes, totalFreeBytes;
    if (!GetDiskFreeSpaceExA(rootPath, &freeBytes, &totalBytes, &totalFreeBytes)) {
        set_console_color(COLOR_RED);
        printf("无法获取磁盘信息\n");
        set_console_color(COLOR_RESET);
        return;
    }

    char volumeName[256] = { 0 };
    char fileSystem[10] = { 0 };
    DWORD serialNumber = 0;
    get_drive_details(driveLetter, volumeName, fileSystem, &serialNumber);

    double totalBytesD = (double)totalBytes.QuadPart;
    double freeBytesD = (double)freeBytes.QuadPart;
    double usedBytesD = totalBytesD - freeBytesD;

    double totalGB = totalBytesD / static_cast<double>(1024 * 1024 * 1024);
    double freeGB = freeBytesD / static_cast<double>(1024 * 1024 * 1024);
    double usedGB = usedBytesD / static_cast<double>(1024 * 1024 * 1024);

    const char* deviceType = get_device_type_name(GetDriveTypeA(rootPath));

    set_console_color(COLOR_CYAN);
    printf("\n[%c:]详细信息\n", driveLetter);
    printf("===========================================\n");
    set_console_color(COLOR_RESET);

    printf("设备类型: %-10s\n", deviceType);
    printf("连接模式: %-10s\n", busType.c_str());
    printf("产品型号: %-28s\n", productInfo);
    printf("卷标名称: %-24s\n", volumeName);
    printf("文件系统: %-8s\n", fileSystem);
    printf("序列号: %08lX\n", (unsigned long)serialNumber);
    printf("总存储空间: %.2f GB\n", totalGB);
    printf("已用空间: %.2f GB\n", usedGB);
    printf("可用空间: %.2f GB\n", freeGB);

    set_console_color(COLOR_CYAN);
    printf("===========================================\n\n");
    set_console_color(COLOR_RESET);
}

void clear_input_buffer() {
    int c;
    while ((c = getchar()) != '\n' && c != EOF);
}

char get_user_input(const char* prompt) {
    printf("%s", prompt);
    char input[10];
    fgets(input, sizeof(input), stdin);
    return toupper(input[0]);
}

//写入进度显示函数
void show_write_progress(
    HANDLE hConsole,
    COORD startPos,
    char driveLetter,
    const char* filename,
    int bufferSizeMB,
    double currentSpeed,
    double avgSpeed,
    double remainingMB,
    double remainingTime,
    BOOL hasError
) {
    // 获取磁盘总空间和可用空间
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    ULARGE_INTEGER freeBytes, totalBytes, totalFreeBytes;
    if (!GetDiskFreeSpaceExA(rootPath, &freeBytes, &totalBytes, &totalFreeBytes)) {
        return;
    }

    // 计算进度百分比
    double totalSpaceMB = (double)totalBytes.QuadPart / (1024.0 * 1024.0);
    double usedSpaceMB = totalSpaceMB - ((double)freeBytes.QuadPart / (1024.0 * 1024.0));
    double progress = usedSpaceMB / totalSpaceMB;

    if (remainingMB < 1) {
        progress = 1.0; //当余量不足1M时, 进度条显示100%
        remainingTime = -1.0; //剩余时间改为-1.0
    }


    const int barWidth = 30;
    int pos = (int)(barWidth * progress);

    SetConsoleCursorPosition(hConsole, startPos);

    // 根据是否有错误选择颜色
    WORD color = hasError ? COLOR_RED : COLOR_GREEN;
    if (currentSpeed < SLOW_WRITE_THRESHOLD) {
        color = COLOR_YELLOW; // 速度过慢显示黄色
    }

    set_console_color(color);
    printf("写入 [");
    for (int i = 0; i < barWidth; ++i) {
        if (i < pos) printf("█");
        else if (i == pos) printf("▌");
        else printf(" ");
    }
    printf(" ] %3d%%", (int)(progress * 100));

    // 格式化文件名显示
    char displayName[30];
    if (hasError) {
        sprintf_s(displayName, "%.12s Error!", filename);
    }
    else {
        strncpy_s(displayName, filename, 20);
        displayName[19] = '\0';
    }

    printf(" | 文件: %s", displayName);
    printf(" | 缓冲区: %2dMB", bufferSizeMB);
    printf(" | 当前速度: %5.2fMB/s", currentSpeed);
    printf(" | 平均速度: %5.2fMB/s", avgSpeed);
    if (remainingMB < 1) {
        printf(" | 剩余空间: - MB");
    }
    else
    {
        printf(" | 剩余空间: %6.0fMB", remainingMB);
    }

    if (remainingTime < 0) {
        printf(" | 剩余时间: --:--");
    }
    else {
        int minutes = (int)remainingTime / 60;
        int seconds = (int)remainingTime % 60;
        printf(" | 剩余时间: %02d:%02d", minutes, seconds);
    }

    set_console_color(COLOR_RESET);
    printf("          "); // 清除可能残留的字符
    fflush(stdout);
}

//验证进度显示函数
void show_verify_progress(
    HANDLE hConsole,
    COORD startPos,
    double totalTestFilesSizeMB,
    double totalVerifiedMB,
    const char* filename,
    int bufferSizeMB,
    double currentSpeed,
    double avgSpeed,
    double remainingMB,
    double remainingTime,
    BOOL hasError
) {
    // 计算进度百分比
    double progress = totalVerifiedMB / totalTestFilesSizeMB;
    if (remainingMB < 1) {
        progress = 1.0; //当余量不足1M时, 进度条显示100%
        remainingTime = -1.0; //剩余时间改为0
    }
    if (progress > 1.0) progress = 1.0;

    const int barWidth = 30;
    int pos = (int)(barWidth * progress);

    SetConsoleCursorPosition(hConsole, startPos);

    // 根据是否有错误选择颜色
    WORD color = hasError ? COLOR_RED : COLOR_GREEN;
    if (currentSpeed < SLOW_VERIFY_THRESHOLD) {
        color = COLOR_YELLOW; // 速度过慢显示黄色
    }

    set_console_color(color);
    printf("验证 [");
    for (int i = 0; i < barWidth; ++i) {
        if (i < pos) printf("█");
        else if (i == pos) printf("▌");
        else printf(" ");
    }
    printf(" ] %3d%%", (int)(progress * 100));

    // 格式化文件名显示
    char displayName[30];
    if (hasError) {
        sprintf_s(displayName, "%.12s Error!", filename);
    }
    else {
        strncpy_s(displayName, filename, 20);
        displayName[19] = '\0';
    }

    printf(" | 文件: %s", displayName);
    printf(" | 缓冲区: %2dMB", bufferSizeMB);
    printf(" | 当前速度: %5.2fMB/s", currentSpeed);
    printf(" | 平均速度: %5.2fMB/s", avgSpeed);
    if (remainingMB < 1) {
        printf(" | 剩余验证: - MB");
    }
    else
    {
        printf(" | 剩余验证: %6.0fMB", remainingMB);
    }

    if (remainingTime < 0) {
        printf(" | 剩余时间: --:--");
    }
    else {
        int minutes = (int)remainingTime / 60;
        int seconds = (int)remainingTime % 60;
        printf(" | 剩余时间: %02d:%02d", minutes, seconds);
    }

    set_console_color(COLOR_RESET);
    printf("          "); // 清除可能残留的字符
    fflush(stdout);
}

//文件状态网络显示函数
void show_file_status_grid(int blocksPerRow, int totalBlocks, const std::vector<int>& blockStatus) {
    int rows = (totalBlocks + blocksPerRow - 1) / blocksPerRow;

    printf("\n文件块状态图:\n");
    printf("[");

    for (int i = 0; i < blocksPerRow * rows; i++) {
        if (i >= totalBlocks) {
            printf(" "); // 空白填充
            continue;
        }

        if (i % blocksPerRow == 0 && i > 0) {
            printf("]\n["); // 换行
        }

        // 根据状态设置颜色和字符
        switch (blockStatus[i]) {
        case 0: // 正常
            set_console_color(COLOR_GREEN);
            printf("■");
            break;
        case 1: // 校验错误
            set_console_color(COLOR_RED);
            printf("■");
            break;
        case 2: // 读取错误
            set_console_color(COLOR_YELLOW);
            printf("■");
            break;
        case -1: // 未知
            set_console_color(COLOR_WHITE);
            printf("?");
            break;
        default: // 其他
            set_console_color(COLOR_WHITE);
            printf("?");
            break;
        }
        set_console_color(COLOR_RESET);
    }
    printf("]\n\n");

    // 添加图例
    set_console_color(COLOR_GREEN);
    printf("■ 正常 ");
    set_console_color(COLOR_RED);
    printf("■ 校验错误 ");
    set_console_color(COLOR_YELLOW);
    printf("■ 读取错误 ");
    set_console_color(COLOR_WHITE);
    printf("? 未知\n");
    set_console_color(COLOR_RESET);
}

void show_scaled_file_status_grid(int originalTotalBlocks, const std::vector<int>& originalBlockStatus) {
    // 计算缩放因子
    int scaleFactor = 1;
    int scaledTotalBlocks = originalTotalBlocks;

    if (originalTotalBlocks > 2048) {
        scaleFactor = (int)ceil((double)originalTotalBlocks / 2048.0);
        scaledTotalBlocks = originalTotalBlocks / scaleFactor;

        // 确保缩放后的块数不超过2048
        if (scaledTotalBlocks > 2048) {
            scaleFactor *= 2;
            scaledTotalBlocks = originalTotalBlocks / scaleFactor;
        }
    }

    // 创建缩放后的状态数组
    std::vector<int> scaledBlockStatus(scaledTotalBlocks, 0);

    // 修改合并块状态的逻辑 - 调整优先级
    for (int i = 0; i < scaledTotalBlocks; i++) {
        int errorCount = 0;        // 校验错误计数（红色）
        int readErrorCount = 0;     // 读取错误计数（黄色）
        int unknownCount = 0;       // 未知状态计数

        for (int j = 0; j < scaleFactor && (i * scaleFactor + j) < originalTotalBlocks; j++) {
            int originalStatus = originalBlockStatus[i * scaleFactor + j];

            if (originalStatus == 1) {         // 校验错误（红色）
                errorCount++;
            }
            else if (originalStatus == 2) {  // 读取错误（黄色）
                readErrorCount++;
            }
            else if (originalStatus == -1) {  // 未知状态
                unknownCount++;
            }
        }

        // 修改优先级：红色 > 黄色 > 未知 > 正常
        if (errorCount > 0) {
            scaledBlockStatus[i] = 1; // 校验错误（红色）优先
        }
        else if (readErrorCount > 0) {
            scaledBlockStatus[i] = 2; // 读取错误（黄色）
        }
        else if (unknownCount == scaleFactor) {
            scaledBlockStatus[i] = -1; // 全部未知
        }
        else {
            scaledBlockStatus[i] = 0; // 正常
        }
    }

    // 显示缩放后的网格
    show_file_status_grid(64, scaledTotalBlocks, scaledBlockStatus);

    // 显示缩放信息
    if (scaleFactor > 1) {
        set_console_color(COLOR_CYAN);
        printf("缩放比例: 1:%d (每个方块代表 %d MB 数据)\n", scaleFactor, scaleFactor);
        set_console_color(COLOR_RESET);
    }
}

//字符串替换函数
char* replace_string(const char* source, const char* oldStr, const char* newStr) {
    if (!source || !oldStr || !newStr) return nullptr;

    size_t sourceLen = strlen(source);
    size_t oldStrLen = strlen(oldStr);
    size_t newStrLen = strlen(newStr);

    // 计算替换次数
    size_t count = 0;
    const char* tmp = source;
    while ((tmp = strstr(tmp, oldStr)) != nullptr) {
        count++;
        tmp += oldStrLen;
    }

    // 计算新字符串长度（包括终止符）
    size_t newLen = sourceLen + count * (newStrLen - oldStrLen);
    char* result = (char*)malloc(newLen + 1); // +1 for null terminator
    if (!result) return nullptr;

    char* current = result;
    const char* start = source;
    const char* end = source;
    size_t remaining = newLen + 1; // 剩余缓冲区大小（包括终止符）

    while ((end = strstr(start, oldStr)) != nullptr) {
        // 计算非匹配部分的长度
        size_t chunkLen = end - start;

        // 安全复制非匹配部分
        if (chunkLen > 0) {
            size_t toCopy = min(chunkLen, remaining - 1); // 保留1字节给终止符
            if (toCopy > 0) {
                strncpy_s(current, remaining, start, toCopy);
                current += toCopy;
                remaining -= toCopy;
            }
        }

        // 安全复制新字符串
        size_t toCopy = min(newStrLen, remaining - 1); // 保留1字节给终止符
        if (toCopy > 0) {
            strncpy_s(current, remaining, newStr, toCopy);
            current += toCopy;
            remaining -= toCopy;
        }

        // 移动指针
        start = end + oldStrLen;
    }

    // 安全复制剩余部分
    size_t chunkLen = strlen(start);
    size_t toCopy = min(chunkLen, remaining - 1); // 保留1字节给终止符
    if (toCopy > 0) {
        strncpy_s(current, remaining, start, toCopy);
        current += toCopy;
        remaining -= toCopy;
    }

    // 添加终止符
    if (remaining > 0) {
        *current = '\0';
    }
    else {
        // 确保终止符存在
        result[newLen] = '\0';
    }

    return result;
}

//结果模式显示
void show_result_pattern(int status, UINT deviceType) {
    // 根据设备类型选择图标
    const char* iconTemplate = nullptr;
    if (deviceType == DRIVE_REMOVABLE) {
        // U盘图标
        iconTemplate =
            "\t ********* \n"
            "\t *  ╔══════╗    *\n"
            "\t * ╔╝  USB ╚╗   *\n"
            "\t *╔╝        ╚╗  *\n"
            "\t *║    +    ║  *\n"
            "\t *╚╗        ╔╝  *\n"
            "\t * ╚╗      ╔╝   *\n"
            "\t *  ╚══════╝    *\n"
            "\t ********* \n";
    }
    else {
        // 硬盘图标
        iconTemplate =
            "\t*********\n"
            "\t* ╔════════╗   *\n"
            "\t*╔╝        ╚╗  *\n"
            "\t*║          ║  *\n"
            "\t*║    +    ║  *\n"
            "\t*║          ║  *\n"
            "\t*╚╗        ╔╝  *\n"
            "\t* ╚════════╝   *\n"
            "\t*********\n";
    }

    char* icon;

    // 根据状态选择颜色和符号
    WORD color;
    switch (status) {
    case 0: // 失败
        color = COLOR_RED;
        icon = replace_string(iconTemplate, "*", "×");
        icon = replace_string(icon, "+", "NO");
        break;
    case 1: // 成功
        color = COLOR_GREEN;
        icon = replace_string(iconTemplate, "*", "√");
        icon = replace_string(icon, "+", "OK");
        break;
    case 2: // 警告
        color = COLOR_YELLOW;
        icon = replace_string(iconTemplate, "*", "！");
        icon = replace_string(icon, "+", "！");
        break;
    default:
        return;
    }

    if (!icon) {
        // 添加错误处理
        set_console_color(COLOR_RED);
        printf("图标生成失败\n");
        set_console_color(COLOR_RESET);
        return;
    }

    // 在图标下方打印符号
    set_console_color(color);
    printf("\n");
    printf("%s", icon);
    set_console_color(COLOR_RESET);

    free(icon); // 释放内存
}

// 显示测试结果
void show_test_result(int totalRounds, int passedRounds, int errors, UINT deviceType) {
    set_console_color(COLOR_WHITE);
    printf("\n执行 %d 轮测试", totalRounds);

    // 计算进度
    double progress = (double)passedRounds / totalRounds;
    WORD color = COLOR_GREEN;

    if (passedRounds == totalRounds && errors == 0) {
        color = COLOR_GREEN;
        set_console_color(color);
        printf(" - 全部通过验证无错误!\n");
        show_result_pattern(1, deviceType);
    }
    else if (errors > 0) {
        color = COLOR_RED;
        set_console_color(color);
        printf(" - 检测到 %d MB 数据错误!\n", errors);
        show_result_pattern(0, deviceType);
    }
    else {
        color = COLOR_YELLOW;
        set_console_color(color);
        printf(" - %d/%d 轮通过验证!\n", passedRounds, totalRounds);
        show_result_pattern(2, deviceType);
    }

    // 显示总结进度条
    set_console_color(color);
    printf("\n[");
    //int pos = 30 * progress;
    int pos = static_cast<int>(30 * progress + 0.5);  //添加四舍五入
    for (int i = 0; i < 30; ++i) {
        if (i < pos) printf("█");
        else if (i == pos && pos % 2 == 1 && progress > 0.5) printf("▊");
        else if (i == pos && pos % 2 == 0 && progress > 0.5) printf("█");
        else printf(" ");
    }
    printf(" ] %3d%%", (int)(progress * 100));
    set_console_color(COLOR_RESET);
    printf("\n");
}

// 文件检查
int check_existing_files(char driveLetter) {
    int fileCount = 0;

    int i = 0;
    while (!g_bExit)
    {
        i++;
        char tempFile[MAX_PATH];
        sprintf_s(tempFile, "%c:\\DRW%05d.BIN", driveLetter, i);
        if (GetFileAttributesA(tempFile) != INVALID_FILE_ATTRIBUTES) {
            fileCount++;
        }
        else {
            break;
        }
    }
    return fileCount > 0;
}

double get_current_time() {
    static LARGE_INTEGER frequency;
    static BOOL initialized = FALSE;

    if (!initialized) {
        QueryPerformanceFrequency(&frequency);
        initialized = TRUE;
    }

    LARGE_INTEGER current;
    QueryPerformanceCounter(&current);
    return (double)current.QuadPart / (double)frequency.QuadPart;
}

// 删除测试文件
void delete_test_files(char driveLetter) {
    set_console_color(COLOR_YELLOW);
    printf("\n删除测试文件...\n");

    if (logFile) {
        write_log("删除测试文件");
    }

    int fileDeleted = 0;
    for (int i = 1; ; i++) {
        char fileName[MAX_PATH];
        sprintf_s(fileName, "%c:\\DRW%05d.BIN", driveLetter, i);

        if (remove(fileName) != 0) {
            if (errno == ENOENT) break; // 文件不存在, 停止删除

            set_console_color(COLOR_RED);
            printf("文件删除失败: %s (错误: %d)\n", fileName, errno);
            set_console_color(COLOR_RESET);

            if (logFile) {
                write_log("文件删除失败: %s (错误: %d)", fileName, errno);
            }
        }
        else {
            fileDeleted++;
        }
    }

    if (fileDeleted > 0) {
        set_console_color(COLOR_GREEN);
        printf("已删除 %d 个文件\n", fileDeleted);
        set_console_color(COLOR_RESET);

        if (logFile) {
            write_log("已删除 %d 个文件", fileDeleted);
        }
    }
    else {
        set_console_color(COLOR_YELLOW);
        printf("未找到测试文件\n");
        set_console_color(COLOR_RESET);
    }
}

// 调整缓冲区大小
void adjust_buffer_size() {
    if (targetFileSize == 2048) {
        bufferSize = largeBufferSize;
        if (logFile) {
            write_log("使用大缓冲区: 16MB");
        }
    }
    else {
        bufferSize = 1 * 1024 * 1024;
    }
}

// 超时检测线程函数
DWORD WINAPI IOWatchdogThread(LPVOID lpParam) {
    while (!g_bExit) {
        // 等待事件或100毫秒超时
        DWORD waitResult = WaitForSingleObject(g_hWatchdogEvent, 100);
        if (waitResult == WAIT_OBJECT_0) {
            break; // 事件被触发，退出线程
        }

        EnterCriticalSection(&csTimeout);
        ULONGLONG currentTime = GetTickCount64();
        ULONGLONG elapsedTime = currentTime - lastActivityTime;
        LeaveCriticalSection(&csTimeout);

        // 如果超过超时时间且没有退出标志, 设置超时标志
        if (elapsedTime > IO_TIMEOUT && !g_bExit) {
            g_bIOTimeout = TRUE;

            // 记录超时事件
            if (logFile) {
                write_log("I/O操作超时检测: 已等待 %llu ms", elapsedTime);
            }

            // 更新活动时间
            EnterCriticalSection(&csTimeout);
            lastActivityTime = currentTime;
            LeaveCriticalSection(&csTimeout);
        }
    }
    return 0;
}

// 设备状态检测
BOOL IsDriveAvailable(char driveLetter, ULONGLONG dwTimeoutMs) {
    char rootPath[] = { driveLetter, ':', '\\', '\0' };

    DWORD attributes = GetFileAttributesA(rootPath);
    if (attributes != INVALID_FILE_ATTRIBUTES) {
        return TRUE; // 设备可用
    }

    // 如果设备不可用, 等待并重试
    ULONGLONG startTime = GetTickCount64();
    while (GetTickCount64() - startTime < dwTimeoutMs) {
        Sleep(100); // 短暂等待
        attributes = GetFileAttributesA(rootPath);
        if (attributes != INVALID_FILE_ATTRIBUTES) {
            return TRUE; // 设备恢复
        }
    }

    return FALSE; // 设备超时未恢复
}

// 多线程写入函数
DWORD WINAPI WriteThread(LPVOID lpParam) {
    ThreadParams* params = (ThreadParams*)lpParam;
    int bufferSizeForThisFile = params->bufferSizeForThisFile;
    LPVOID buffer = _aligned_malloc(bufferSizeForThisFile, bytesPerSector);

    // 使用线程参数中的状态副本, 而不是全局状态
    unsigned int local_state[4];
    memcpy(local_state, params->initial_state, sizeof(local_state));

    for (LONGLONG blockIndex = params->startBlock;
        blockIndex < params->endBlock && !g_bExit && !g_bErrorExit;  // 添加!g_bErrorExit条件
        blockIndex++) {

        // 在每次操作前检查设备状态
        BOOL bReconnected = FALSE;
        if (!IsDriveAvailableEx(selectedDrive, 1000, &bReconnected)) {
            if (bReconnected) {
                // 设备重新连接，需要重新打开文件句柄
                CloseHandle(params->hFile);

                char fileName[MAX_PATH];
                sprintf_s(fileName, "%c:\\DRW%05d.BIN", selectedDrive,
                    (int)(params->startBlock / (targetFileSize * 1024 * 1024 / bufferSize)) + 1);

                params->hFile = ReopenFileHandle(fileName, GENERIC_WRITE, 0, OPEN_EXISTING);
                if (params->hFile == INVALID_HANDLE_VALUE) {
                    write_log("设备重新连接后无法重新打开文件");
                    break;
                }

                write_log("设备重新连接，文件句柄已恢复");
                continue; // 重新尝试当前操作
            }
            else {
                // 设备不可用，等待
                Sleep(1000);
                continue;
            }
        }

        // 使用状态副本生成数据
        generate_block_with_state(buffer, bufferSizeForThisFile, local_state);

        // 设置异步I/O结构
        OVERLAPPED overlapped = { 0 };
        overlapped.Offset = (DWORD)(blockIndex * bufferSizeForThisFile);
        overlapped.OffsetHigh = (DWORD)((blockIndex * bufferSizeForThisFile) >> 32);
        overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (overlapped.hEvent == NULL) {
            DWORD err = GetLastError();
            write_log("CreateEvent failed in WriteThread: error %lu", err);
            _aligned_free(buffer);
            return 1; // 退出线程
        }

        // 更新活动时间
        EnterCriticalSection(&csTimeout);
        lastActivityTime = GetTickCount64();
        LeaveCriticalSection(&csTimeout);

        // 异步写入（带重试机制）
        DWORD bytesWritten = 0;
        BOOL writeSuccess = FALSE;

        for (int retry = 0; retry < RETRY_COUNT && !writeSuccess && !g_bExit; retry++) {
            BOOL result = WriteFile(
                params->hFile,
                buffer,
                bufferSizeForThisFile,
                NULL,
                &overlapped
            );

            if (!result) {
                DWORD err = GetLastError();
                if (err == ERROR_IO_PENDING) {
                    // 等待操作完成（带超时）
                    DWORD waitResult;
                    if (overlapped.hEvent != NULL) {
                        waitResult = WaitForSingleObject(overlapped.hEvent, IO_TIMEOUT);
                    }
                    else {
                        // 处理错误
                        write_log("Error: overlapped.hEvent is NULL in WaitForSingleObject");
                    }

                    if (waitResult == WAIT_TIMEOUT) {
                        // 超时处理
                        CancelIo(params->hFile);

                        // 检查设备状态
                        if (!IsDriveAvailable(selectedDrive, 1000)) {
                            DWORD retryDelay = 1000 * (1 << retry); // 指数退避
                            write_log("设备不可用, 等待 %d ms 后重试 %d/%d", retryDelay, retry + 1, RETRY_COUNT);
                            Sleep(retryDelay);
                            continue; // 重试
                        }

                        // 更新活动时间
                        EnterCriticalSection(&csTimeout);
                        lastActivityTime = GetTickCount64();
                        LeaveCriticalSection(&csTimeout);
                        continue; // 重试
                    }
                    else if (waitResult == WAIT_OBJECT_0) {
                        // 操作完成
                        writeSuccess = GetOverlappedResult(params->hFile, &overlapped, &bytesWritten, TRUE);
                    }
                }
                else {
                    // 其他错误
                    break;
                }
            }
            else {
                // 同步完成
                writeSuccess = TRUE;
                bytesWritten = bufferSizeForThisFile;
            }

            // 更新活动时间
            EnterCriticalSection(&csTimeout);
            lastActivityTime = GetTickCount64();
            LeaveCriticalSection(&csTimeout);
        }

        // 检查写入是否完整
        if (!writeSuccess || bytesWritten != bufferSizeForThisFile) {
            globalErrors++;

            // 新增错误退出逻辑
            if (!continueOnError) {
                g_bErrorExit = TRUE;  // 设置全局错误退出标志
                write_log("检测到写入错误且设置为不继续, 终止测试");
                break;  // 立即退出循环
            }

            // 原有继续逻辑
            if (!continueOnError) break;
        }

        globalBlocksCompleted++;
        CloseHandle(overlapped.hEvent);
    }

    _aligned_free(buffer);
    return 0;
}

// 多线程验证函数
DWORD WINAPI VerifyThread(LPVOID lpParam) {
    ThreadParams* params = (ThreadParams*)lpParam;
    int bufferSizeForThisFile = params->bufferSizeForThisFile;
    LPVOID buffer = _aligned_malloc(bufferSizeForThisFile, bytesPerSector);

    //计算每个缓冲区对应的1MB块数
    int blocksPerBuffer = (params->bufferSizeForThisFile + (1024 * 1024) - 1) / (1024 * 1024);
    if (blocksPerBuffer < 1) blocksPerBuffer = 1; // 确保至少1块

    // 使用线程参数中的状态副本
    unsigned int local_state[4];
    memcpy(local_state, params->initial_state, sizeof(local_state));

    // 计算全局块索引偏移
    LONGLONG globalBlockOffset = params->startBlock;

    for (LONGLONG blockIndex = params->startBlock;
        blockIndex < params->endBlock && !g_bExit && !g_bErrorExit;  // 添加!g_bErrorExit条件
        blockIndex++) {

        // 更新活动时间
        EnterCriticalSection(&csTimeout);
        lastActivityTime = GetTickCount64();
        LeaveCriticalSection(&csTimeout);

        // 设置异步I/O结构
        OVERLAPPED overlapped = { 0 };
        overlapped.Offset = (DWORD)(blockIndex * bufferSizeForThisFile);
        overlapped.OffsetHigh = (DWORD)((blockIndex * bufferSizeForThisFile) >> 32);
        overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (overlapped.hEvent == NULL) {
            DWORD err = GetLastError();
            write_log("CreateEvent failed in VerifyThread: error %lu", err);
            _aligned_free(buffer);
            return 1; // 退出线程
        }

        // 异步读取（带重试机制）
        DWORD bytesRead = 0;
        BOOL readSuccess = FALSE;
        BOOL hasError = FALSE;

        for (int retry = 0; retry < RETRY_COUNT && !readSuccess && !g_bExit; retry++) {
            BOOL result = ReadFile(
                params->hFile,
                buffer,
                bufferSizeForThisFile,
                NULL,
                &overlapped
            );

            if (!result) {
                DWORD err = GetLastError();
                if (err == ERROR_IO_PENDING) {
                    // 等待操作完成（带超时）
                    DWORD waitResult;
                    if (overlapped.hEvent != NULL) {
                        waitResult = WaitForSingleObject(overlapped.hEvent, IO_TIMEOUT);
                    }
                    else {
                        // 处理错误
                        write_log("Error: overlapped.hEvent is NULL in WaitForSingleObject");
                    }

                    if (waitResult == WAIT_TIMEOUT) {
                        // 超时处理
                        CancelIo(params->hFile);

                        // 检查设备状态
                        if (!IsDriveAvailable(selectedDrive, 1000)) {
                            DWORD retryDelay = 1000 * (1 << retry); // 指数退避
                            write_log("设备不可用, 等待 %d ms 后重试 %d/%d", retryDelay, retry + 1, RETRY_COUNT);
                            Sleep(retryDelay);
                            continue; // 重试
                        }

                        // 更新活动时间
                        EnterCriticalSection(&csTimeout);
                        lastActivityTime = GetTickCount64();
                        LeaveCriticalSection(&csTimeout);
                        continue; // 重试
                    }
                    else if (waitResult == WAIT_OBJECT_0) {
                        // 操作完成
                        readSuccess = GetOverlappedResult(params->hFile, &overlapped, &bytesRead, TRUE);
                    }
                }
                else {
                    // 其他错误
                    break;
                }
            }
            else {
                // 同步完成
                readSuccess = TRUE;
                bytesRead = bufferSizeForThisFile;
            }

            // 更新活动时间
            EnterCriticalSection(&csTimeout);
            lastActivityTime = GetTickCount64();
            LeaveCriticalSection(&csTimeout);
        }

        // 错误处理和状态记录
        LONGLONG baseGlobalIndex = params->globalBlockOffset + (blockIndex * bufferSizeForThisFile) / (1024 * 1024);

        // 错误处理
        if (!readSuccess) {
            // 读取失败, 设置多个块为读取错误状态
            for (int i = 0; i < blocksPerBuffer; i++) {
                LONGLONG globalIndex = baseGlobalIndex + i;
                if (globalIndex < static_cast<LONGLONG>(globalBlockStatus.size())) {
                    globalBlockStatus[static_cast<unsigned int>(globalIndex)] = 2; // 读取错误
                }
            }
            globalErrors++;
            hasError = TRUE;

            // 新增: 如果设置不继续, 则设置错误退出标志
            if (!continueOnError) {
                g_bErrorExit = TRUE;
                break;
            }
        }
        else if (bytesRead != bufferSizeForThisFile) {
            // 读取不完整, 设置多个块为读取错误状态
            for (int i = 0; i < blocksPerBuffer; i++) {
                LONGLONG globalIndex = baseGlobalIndex + i;
                if (globalIndex < static_cast<LONGLONG>(globalBlockStatus.size())) {
                    globalBlockStatus[static_cast<unsigned int>(globalIndex)] = 2; // 读取错误
                }
            }
            globalErrors++;
            hasError = TRUE;

            if (!continueOnError) {
                g_bErrorExit = TRUE;
                break;
            }
        }
        else if (!verify_block_with_state((int*)buffer, bufferSizeForThisFile, local_state)) {         // 使用状态副本验证数据
            // 验证失败, 设置多个块为校验错误状态
            for (int i = 0; i < blocksPerBuffer; i++) {
                LONGLONG globalIndex = baseGlobalIndex + i;
                if (globalIndex < static_cast<LONGLONG>(globalBlockStatus.size())) {
                    globalBlockStatus[static_cast<unsigned int>(globalIndex)] = 1; // 校验错误
                }
            }
            globalErrors++;
            hasError = TRUE;

            if (!continueOnError) {
                g_bErrorExit = TRUE;
                break;
            }
        }
        else {
            // 验证成功, 记录块状态为校验正常
            for (int i = 0; i < blocksPerBuffer; i++) {
                LONGLONG globalIndex = baseGlobalIndex + i;
                if (globalIndex < static_cast<LONGLONG>(globalBlockStatus.size())) {
                    globalBlockStatus[static_cast<unsigned int>(globalIndex)] = 0; // 正常
                }
            }
        }

        // 总是更新完成块计数
        globalBlocksCompleted++;

        CloseHandle(overlapped.hEvent);

        // 遇到错误且设置不继续时退出
        if (hasError && !continueOnError) {
            break;
        }
    }

    _aligned_free(buffer);
    return 0;
}

// 在工具函数部分添加: 
BOOL get_disk_space_info(char driveLetter, ULARGE_INTEGER& freeBytes, ULARGE_INTEGER& totalBytes) {
    char rootPath[4] = { driveLetter, ':', '\\', '\0' };
    return GetDiskFreeSpaceExA(rootPath, &freeBytes, &totalBytes, NULL);
}

// 辅助函数: 检查日志行格式是否有效（以 [YYYY-MM-DD HH:MM:SS] 开头）
int isValidLogLine(const char* line) {
    if (strlen(line) < 21) return 0; // 至少需要21个字符
    if (line[0] != '[') return 0;
    // 检查年份部分（索引1-4）
    for (int i = 1; i <= 4; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[5] != '-') return 0;
    // 检查月份部分（索引6-7）
    for (int i = 6; i <= 7; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[8] != '-') return 0;
    // 检查日期部分（索引9-10）
    for (int i = 9; i <= 10; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[11] != ' ') return 0; // 索引11应为空格
    // 检查小时部分（索引12-13）
    for (int i = 12; i <= 13; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[14] != ':') return 0; // 索引14应为冒号
    // 检查分钟部分（索引15-16）
    for (int i = 15; i <= 16; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[17] != ':') return 0; // 索引17应为冒号
    // 检查秒钟部分（索引18-19）
    for (int i = 18; i <= 19; i++) {
        if (line[i] < '0' || line[i] > '9') return 0;
    }
    if (line[20] != ']') return 0; // 索引20应为右括号
    return 1;
}

// 辅助函数: 将时间字符串转换为 time_t
time_t parseTimestamp(const char* timestamp) {
    struct tm tm = { 0 };
    sscanf_s(timestamp, "[%d-%d-%d %d:%d:%d]",
        &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
        &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
    tm.tm_year -= 1900;
    tm.tm_mon -= 1;
    return mktime(&tm);
}

// 主函数: 导出异常测试报告
void export_exception_test_report(const char* logFilePath) {
    FILE* logFile;
    errno_t err = fopen_s(&logFile, logFilePath, "r");
    if (err != 0 || !logFile) {
        printf("无法打开日志文件: %s\n", logFilePath);
        return;
    }

    if (logFile != nullptr) {
        // 记录开始时间
        time_t startTime = time(nullptr);
        int lineCount = 0;
        int passedRounds = 0;
        int testRounds = 0; // 总测试轮次
        int currentRound = 0; //已执行轮次
        int errorRounds = 0; //失败次数
        int errorMB = 0; // 错误数据量（MB） - 改为int
        char line[256];
        char driveFromLog = 0; // 从日志中提取的驱动器字母
        int writeCount = 0;
        double nominalCapacity = 0; // 标称容量
        double actualCapacity = 0; // 实际容量
        double totalWriteData = 0.0;
        double totalVerifyData = 0.0;
        double maxWriteSpeed = 0.0;
        double maxVerifySpeed = 0.0;
        double totalWriteCurrentSpeed = 0.0;
        double totalVerifyCurrentSpeed = 0.0;
        int verifyCount = 0;
        time_t firstTimestamp = 0;
        time_t lastTimestamp = 0;

        while (fgets(line, sizeof(line), logFile) != nullptr) {
            lineCount++;

            // 首先统一化逗号格式: 将中文逗号替换为英文逗号
            std::string lineStr(line);
            size_t pos = 0;
            while ((pos = lineStr.find("，", pos)) != std::string::npos) {
                lineStr.replace(pos, 2, ","); // 中文逗号占2字节，替换为英文逗号
                pos += 1;
            }
            while ((pos = lineStr.find("：", pos)) != std::string::npos) {
                lineStr.replace(pos, 2, ":"); // 中文冒号占2字节，替换为英文冒号
                pos += 1;
            }
            // 将处理后的字符串拷贝回line缓冲区
            strcpy_s(line, sizeof(line), lineStr.c_str());

            // 检查通过轮数
            if (strstr(line, "轮验证通过") != nullptr) {
                passedRounds++;
            }

            // 检查写入或验证失败
            if (strstr(line, "写入失败") != nullptr || strstr(line, "验证失败") != nullptr) {
                errorRounds++;
            }

            // 检查测试设备信息
            if (strstr(line, "测试设备:") != nullptr) {
                char* deviceStart = strstr(line, "测试设备:");
                if (deviceStart != nullptr) {
                    deviceStart += strlen("测试设备:"); // 移动到冒号后面
                    // 跳过空格
                    while (*deviceStart == ' ') deviceStart++;
                    driveFromLog = *deviceStart; // 取第一个字符
                    // 检查是否有效
                    if (driveFromLog >= 'A' && driveFromLog <= 'Z') {
                        // 有效
                        driveFromLog = toupper(driveFromLog);
                    }
                    else if (driveFromLog >= 'a' && driveFromLog <= 'z') {
                        driveFromLog = toupper(driveFromLog);
                    }
                    else {
                        driveFromLog = 0; // 无效
                    }
                }
            }

            // 检查开始测试行, 提取总测试轮次
            if (strstr(line, "开始测试:") != nullptr) {
                char* startPos = strstr(line, "开始测试:");
                if (startPos != nullptr) {
                    startPos += strlen("开始测试:"); // 移动到冒号后面
                    // 跳过空格
                    while (*startPos == ' ') startPos++;
                    // 解析格式: "当前轮次/总轮次"
                    int totalRounds = 0;
                    if (sscanf_s(startPos, "%d/%d", &currentRound, &totalRounds) == 2) {
                        testRounds = totalRounds;
                    }
                }
            }

            // 检查标称容量行, 提取标称容量
            if (strstr(line, "标称容量:") != nullptr) {
                char* startPos = strstr(line, "标称容量:");
                if (startPos != nullptr) {
                    startPos += strlen("标称容量:"); // 移动到冒号后面
                    while (*startPos == ' ') startPos++;
                    double tempCapacity = 0.0;
                    if (sscanf_s(startPos, "%lf", &tempCapacity) == 1) {
                        nominalCapacity = tempCapacity;
                    }
                }
            }

            // 检查实际容量行, 提取实际容量
            if (strstr(line, "实际容量:") != nullptr) {
                char* startPos = strstr(line, "实际容量:");
                if (startPos != nullptr) {
                    startPos += strlen("实际容量:"); // 移动到冒号后面
                    while (*startPos == ' ') startPos++;
                    double tempCapacity = 0.0;
                    if (sscanf_s(startPos, "%lf", &tempCapacity) == 1) {
                        actualCapacity = tempCapacity;
                    }
                }
            }

            // 解析时间戳（如果存在）
            if (strlen(line) >= 20 && line[0] == '[') {
                char timestamp[21];
                strncpy_s(timestamp, sizeof(timestamp), line, 20);
                timestamp[20] = '\0';

                struct tm tm = { 0 };
                if (sscanf_s(timestamp, "[%d-%d-%d %d:%d:%d]",
                    &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
                    &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
                    tm.tm_year -= 1900;
                    tm.tm_mon -= 1;
                    time_t currentTime = mktime(&tm);

                    if (firstTimestamp == 0) {
                        firstTimestamp = currentTime;
                    }
                    lastTimestamp = currentTime;
                }
            }

            // 成功写入相关代码，数据解析逻辑，确保正确解析
            if (strstr(line, "成功写入") != nullptr) {
                // 查找逗号位置（文件名后的第一个逗号）
                char* commaPos = strchr(line, ',');
                if (commaPos != nullptr) {
                    // 跳过逗号和可能存在的空格
                    char* numStart = commaPos + 1;
                    while (*numStart == ' ') numStart++;

                    // 查找"MB"字符串
                    char* mbPos = strstr(numStart, " MB");
                    if (mbPos == nullptr) {
                        mbPos = strstr(numStart, "MB");
                    }

                    if (mbPos != nullptr) {
                        // 提取数字部分
                        char numBuffer[32] = { 0 };
                        size_t numLen = mbPos - numStart;
                        if (numLen > 0 && numLen < sizeof(numBuffer)) {
                            strncpy_s(numBuffer, sizeof(numBuffer), numStart, numLen);
                            double dataSize = atof(numBuffer);
                            if (dataSize >= 0) {
                                totalWriteData += dataSize;

                                // 解析速度信息
                                char* speedPos = strstr(line, "当前速度");
                                if (speedPos != nullptr) {
                                    double currentSpeed = 0.0;
                                    if (sscanf_s(speedPos, "当前速度 %lf", &currentSpeed) == 1) {
                                        totalWriteCurrentSpeed += currentSpeed;
                                        writeCount++;
                                        if (currentSpeed > maxWriteSpeed) {
                                            maxWriteSpeed = currentSpeed;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // 解析成功验证行
            if (strstr(line, "成功验证") != nullptr) {
                // 查找逗号位置（文件名后的第一个逗号）
                char* commaPos = strchr(line, ',');
                if (commaPos != nullptr) {
                    // 跳过逗号和可能存在的空格
                    char* numStart = commaPos + 1;
                    while (*numStart == ' ') numStart++;

                    // 查找"MB"字符串
                    char* mbPos = strstr(numStart, " MB");
                    if (mbPos == nullptr) {
                        mbPos = strstr(numStart, "MB");
                    }

                    if (mbPos != nullptr) {
                        // 提取数字部分
                        char numBuffer[32] = { 0 };
                        size_t numLen = mbPos - numStart;
                        if (numLen > 0 && numLen < sizeof(numBuffer)) {
                            strncpy_s(numBuffer, sizeof(numBuffer), numStart, numLen);
                            double dataSize = atof(numBuffer);
                            if (dataSize >= 0) {
                                totalVerifyData += dataSize;

                                // 解析速度信息
                                char* speedPos = strstr(line, "当前速度");
                                if (speedPos != nullptr) {
                                    double currentSpeed = 0.0;
                                    if (sscanf_s(speedPos, "当前速度 %lf", &currentSpeed) == 1) {
                                        totalVerifyCurrentSpeed += currentSpeed;
                                        verifyCount++;
                                        if (currentSpeed > maxVerifySpeed) {
                                            maxVerifySpeed = currentSpeed;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // 检查验证失败行, 提取错误数据量
            if (strstr(line, "验证失败") != nullptr) {
                // 查找逗号位置（文件名后的第一个逗号）
                char* commaPos = strchr(line, ',');
                if (commaPos != nullptr) {
                    // 跳过逗号和可能存在的空格
                    char* numStart = commaPos + 1;
                    while (*numStart == ' ') numStart++;

                    // 查找"MB"字符串
                    char* mbPos = strstr(numStart, " MB");
                    if (mbPos == nullptr) {
                        mbPos = strstr(numStart, "MB");
                    }

                    if (mbPos != nullptr) {
                        // 提取数字部分
                        char numBuffer[32] = { 0 };
                        size_t numLen = mbPos - numStart;
                        if (numLen > 0 && numLen < sizeof(numBuffer)) {
                            strncpy_s(numBuffer, sizeof(numBuffer), numStart, numLen);
                            double dataSize = atof(numBuffer);
                            if (dataSize > 0) {
                                // 使用四舍五入转换为整数MB
                                errorMB += static_cast<int>(dataSize + 0.5);
                            }
                        }
                    }
                }
            }

            //其他处理逻辑补充...
        }

        fclose(logFile);

        // 计算平均速度
        double avgWriteSpeed = (writeCount > 0) ? totalWriteCurrentSpeed / writeCount : 0.0;
        double avgVerifySpeed = (verifyCount > 0) ? totalVerifyCurrentSpeed / verifyCount : 0.0;

        // 计算测试总时长
        double totalTimeSeconds = 0.0;
        if (firstTimestamp != 0 && lastTimestamp != 0) {
            totalTimeSeconds = difftime(lastTimestamp, firstTimestamp);
        }

        // 准备驱动器字符串
        char driveLetter[10] = { 0 };
        if (driveFromLog != 0) {
            driveLetter[0] = driveFromLog;
            driveLetter[1] = ':';
            driveLetter[2] = '\0';
        }

        // 生成结果消息
        char result[256];
        if (errorMB > 0) {
            sprintf_s(result, "测试被中断, 检测到 %d MB 数据错误", errorMB);
        }
        else {
            sprintf_s(result, "测试被中断, 已完成 %d 轮验证无错误", passedRounds);
        }

        // 获取总线类型
        std::string busType = "未知";
        if (driveFromLog != 0) {
            busType = get_disk_bus_type(driveFromLog);
        }

        // 在生成报告时使用提取的数据
        // 注意: 如果 testRounds 为 0, 则使用默认值 1, 避免除零错误
        if (testRounds == 0) {
            testRounds = 1;
        }
        if (currentRound == 0) {
            currentRound = 1;
        }

        //导出测试报告必须记录至全局变量
        totalWrittenInRound = totalWriteData;
        totalVerifiedInRound = totalVerifyData;
        total_average_written_speed = avgWriteSpeed * (testRounds > 0 ? testRounds : 1);
        total_average_verified_speed = avgVerifySpeed * (testRounds > 0 ? testRounds : 1);
        peak_written_speed = maxWriteSpeed;
        peak_verified_speed = maxVerifySpeed;
        total_test_time = totalTimeSeconds;

        //添加全局变量赋值
        totalWrittenInRound = totalWriteData;
        totalVerifiedInRound = totalVerifyData;

        if (nominalCapacity == 0) nominalCapacity = static_cast<double>(totalWriteData / currentRound + 0.5); // 标称容量,当无法获取时，则按写入文件大小获取默认值
        if (actualCapacity == 0) actualCapacity = static_cast<double>(totalVerifyData / currentRound + 0.5); // 实际容量,当无法获取时，则按校验文件大小获取默认值

        // 生成异常测试报告
        generate_report(driveLetter, testRounds, currentRound, passedRounds, errorMB, nominalCapacity, actualCapacity, result, busType.c_str(), nullptr);

        // 生成报告
        printf("===== 异常测试报告 =====\n");
        if (driveFromLog) {
            printf("测试设备: %s\n", driveLetter);
        }
        else {
            printf("测试设备: 未找到\n");
        }
        // 输出统计信息
        printf("读取文件大小总共 %d 行, 用时 %.2f 秒\n", lineCount, totalTimeSeconds);
        printf("总写入数据量: %.2f MB\n", totalWriteData);
        printf("平均写入速度: %.2f MB/s\n", avgWriteSpeed);
        printf("峰值写入速度: %.2f MB/s\n", maxWriteSpeed);
        printf("总验证数据量: %.2f MB\n", totalVerifyData);
        printf("平均验证速度: %.2f MB/s\n", avgVerifySpeed);
        printf("峰值验证速度: %.2f MB/s\n", maxVerifySpeed);
        printf("写入和校验失败总计: %d 次\n", errorRounds);

        // 使用四舍五入转换时间
        int totalMinutes = static_cast<int>((totalTimeSeconds / 60) + 0.5);
        printf("测试总时长: %.2f 秒 (约 %d 分钟)\n", totalTimeSeconds, totalMinutes);

        // 删除临时日志文件
        if (remove(logFilePath) == 0) {
            printf("已删除临时日志文件\n");
        }
        else {
            printf("删除临时日志文件失败\n");
        }
    }
}

// 检查文件是否被占用的函数
bool isFileLocked(const char* filename) {
    HANDLE hFile = CreateFileA(
        filename,
        GENERIC_READ | GENERIC_WRITE,
        0, // 不共享
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );

    if (hFile == INVALID_HANDLE_VALUE) {
        DWORD err = GetLastError();
        // 如果文件被占用或者访问被拒绝, 都认为是占用状态
        if (err == ERROR_SHARING_VIOLATION || err == ERROR_ACCESS_DENIED) {
            return true;
        }
        // 文件不存在不算被占用
        if (err == ERROR_FILE_NOT_FOUND) {
            return false;
        }
    }
    else {
        CloseHandle(hFile);
    }
    return false;
}

// 添加一个统一的路径处理函数
std::string get_full_path(const char* filename) {
    char path[MAX_PATH];
    GetModuleFileNameA(NULL, path, MAX_PATH);
    char* lastBackslash = strrchr(path, '\\');
    if (lastBackslash) {
        *(lastBackslash + 1) = '\0';
    }
    strcat_s(path, filename);
    return std::string(path);
}

// 增强设备状态检测函数
BOOL IsDriveAvailableEx(char driveLetter, ULONGLONG dwTimeoutMs, BOOL* pbReconnected) {
    char rootPath[] = { driveLetter, ':', '\\', '\0' };
    static BOOL bLastAvailable = TRUE;
    BOOL bCurrentAvailable = FALSE;

    DWORD attributes = GetFileAttributesA(rootPath);
    if (attributes != INVALID_FILE_ATTRIBUTES) {
        bCurrentAvailable = TRUE;
        // 如果之前不可用但现在可用，说明重新连接
        if (pbReconnected && !bLastAvailable && bCurrentAvailable) {
            *pbReconnected = TRUE;
        }
    }
    else {
        bCurrentAvailable = FALSE;
        if (pbReconnected) *pbReconnected = FALSE;
    }

    bLastAvailable = bCurrentAvailable;
    return bCurrentAvailable;
}

// 增强的文件句柄恢复函数
HANDLE ReopenFileHandle(const char* fileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition) {
    HANDLE hFile = INVALID_HANDLE_VALUE;
    int retryCount = 0;
    const int maxRetries = 10;

    while (retryCount < maxRetries && !g_bExit) {
        hFile = CreateFileA(
            fileName,
            dwDesiredAccess,
            dwShareMode,
            NULL,
            dwCreationDisposition,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
            NULL
        );

        if (hFile != INVALID_HANDLE_VALUE) {
            break; // 成功打开文件
        }

        DWORD error = GetLastError();
        if (error == ERROR_PATH_NOT_FOUND || error == ERROR_DEVICE_NOT_CONNECTED) {
            // 设备可能被拔出，等待重新连接
            printf("设备不可用，等待重新连接... (%d/%d)\n", retryCount + 1, maxRetries);
            Sleep(2000); // 等待2秒
            retryCount++;
        }
        else {
            break; // 其他错误，直接退出
        }
    }

    return hFile;
}

// 在主测试循环中添加设备状态监控
void MonitorDeviceStatus() {
    static ULONGLONG lastCheckTime = 0;
    ULONGLONG currentTime = GetTickCount64();

    if (currentTime - lastCheckTime > 5000) { // 每5秒检查一次
        BOOL bReconnected = FALSE;
        if (!IsDriveAvailableEx(selectedDrive, 1000, &bReconnected)) {
            if (bReconnected) {
                write_log("全局监控：设备重新连接");
            }
        }
        lastCheckTime = currentTime;
    }
}